【Java】【JS】LeetCode - 遞歸 - # 101 對稱二叉樹

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
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章