we are nobody,but we are on the way to be somebody!! 力扣力扣 https://leetcode-cn.com/problems/symmetric-tree/
# 101 對稱二叉樹
給定一個二叉樹,檢查它是否是鏡像對稱的。
進階:你可以運用遞歸和迭代兩種方法解決這個問題嗎?
方法一:遞歸
根據題目的描述,鏡像對稱,就是左右兩邊相等,也就是左子樹和右子樹是相當的。
注意這句話,左子樹和右子相等,也就是說要遞歸的比較左子樹和右子樹。
我們將根節點的左子樹記做 left,右子樹記做 right。比較 left 是否等於 right,不等的話直接返回就可以了。
如果相當,比較 left 的左節點和 right 的右節點,再比較 left 的右節點和 right 的左節點
比如看下面這兩個子樹(他們分別是根節點的左子樹和右子樹),能觀察到這麼一個規律:
左子樹的左孩子 = 右子樹的右孩子
左子樹的右孩子 = 右子樹的左孩子
終止條件:left 和 right 不等,或者 left 和 right 都爲空
/* Java
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null)
return true;
return compare(root.left, root.right);
}
public boolean compare(TreeNode left, TreeNode right){
if(left == null && right == null){ // 停止條件1:兩節點爲空,相等
return true;
}
if(left == null || right == null){ // 停止條件2:兩者有一者爲空,不等
return false;
}
if(left.val != right.val){ // 停止條件3:兩者值不同,不等
return false;
}
// 遞歸比較(左左,右右)&&(左右,右左)
return compare(left.left, right.right)&&compare(left.right, right.left);
}
}
/* javascript
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {boolean}
*/
var isSymmetric = function(root) {
if(root == null){
return true;
}
const check = (left, right)=>{
if(left == null && right == null){
return true;
}else if(left == null || right == null){
return false;
}else{
return left.val === right.val && check(left.left, right.right) && check(left.right, right.left);
}
return false;
}
return check(root.left, root.right);
};
方法二:迭代(隊列)
現在我們改用隊列來實現,思路如下:
首先從隊列中拿出兩個節點(left 和 right)比較
(1)將 left 的 left 節點和 right 的 right 節點放入隊列
(2)將 left 的 right 節點和 right 的 left 節點放入隊列
時間複雜度是 O(n),空間複雜度是 O(n)
// java
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null || (root.left == null && root.right == null)){
return true;
}
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root.left);
queue.add(root.right); // 左右子樹入隊
while(queue.size()>0){
TreeNode left = queue.removeFirst();
TreeNode right = queue.removeFirst(); // 拿出隊列前兩個元素比較
if(left == null && right == null){
continue; // 注意此時隊列可能還有元素,不能return true
}
if(left == null || right == null){
return false;
}
if(left.val != right.val){
return false;
}
queue.add(left.left);
queue.add(right.right);
queue.add(left.right);
queue.add(right.left);
}
return true;
}
}
方法三:棧模擬遞歸
var isSymmetric = (root) => {
if (!root) return true
let leftStack = [], rightStack = [] // 維護兩個棧
let curLeft = root.left // 當前的左子樹
let curRight = root.right // 當前的右子樹
while (curLeft || curRight || leftStack.length || rightStack.length) {
while (curLeft) { // 左子樹存在
leftStack.push(curLeft) // 推入leftStack棧
curLeft = curLeft.left // 不斷將左子樹入棧
}
while (curRight) { // 右子樹存在
rightStack.push(curRight) // 推入rightStack棧
curRight = curRight.right // 不斷將右子樹壓入棧
}
if (leftStack.length !== rightStack.length) return false
// 棧的高度不相等,說明結構不對稱
curLeft = leftStack.pop() // 棧頂節點出棧,賦給curLeft
curRight = rightStack.pop() // 棧頂節點出棧,賦給curRight
if (curLeft.val !== curRight.val) return false
// 兩個棧出棧的節點值不相等 不對稱
curLeft = curLeft.right // 考察左子樹的right
curRight = curRight.left // 考察右子樹的left
}
return true
}