1. 程式人生 > 實用技巧 >每日一道 LeetCode (20):相同的樹

每日一道 LeetCode (20):相同的樹

每天 3 分鐘,走上演算法的逆襲之路。

前文合集

每日一道 LeetCode 前文合集

程式碼倉庫

GitHub: https://github.com/meteor1993/LeetCode

Gitee: https://gitee.com/inwsy/LeetCode

題目:相同的樹

題目來源:https://leetcode-cn.com/problems/same-tree/

給定兩個二叉樹,編寫一個函式來檢驗它們是否相同。

如果兩個樹在結構上相同,並且節點具有相同的值,則認為它們是相同的。

示例 1:

輸入:       1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

輸出: true

示例 2:

輸入:      1          1
          /           \
         2             2

        [1,2],     [1,null,2]

輸出: false

示例 3:

輸入:       1         1
          / \       / \
         2   1     1   2

        [1,2,1],   [1,1,2]

輸出: false

解題思路

今天又見到新的資料結構了,這次遇到的是樹,或者簡單的說是二叉樹。

例行慣例,第一次的見的資料結構基本上都沒啥想法,直接看答案。

只能怨自己肚子裡墨水太少,不會的太多,搞不定的只能答案走起,演算法這玩意,答案背多了再遇到題也就有想法了。

先放一段樹的結構程式碼:

public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
    public TreeNode() {}
    public TreeNode(int val) { this.val = val; }
    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

這段程式碼很簡單,樹上的值是 int 型別,然後有一個左節點有一個右節點。

樹結構介紹完畢,接下來梳理兩種遍歷樹的方案,或者說是常規操作。

解題的話提供兩種方案,一種是遞迴,一種是迴圈。

遞迴

首先極限值判斷,兩個二叉樹都為空肯定相等,如果一個為空另一個不為空肯定不相等。

接下來如果兩個二叉樹都不為空,那麼首先判斷它們的根節點的值是否相同,若不相同則兩個二叉樹一定不同,若相同,再分別判斷兩個二叉樹的左子樹是否相同以及右子樹是否相同,然後接著遞迴這個過程。

迴圈

首先和上面一樣,先進行極限值判斷。

使用兩個佇列分別儲存兩個二叉樹的節點。初始時將兩個二叉樹的根節點分別加入兩個佇列。每次從兩個佇列各取出一個節點,進行操作:

  • 比較兩個節點的值,如果兩個節點的值不相同則兩個二叉樹一定不同。
  • 如果兩個節點的值相同,則判斷兩個節點的子節點是否為空,如果只有一個節點的左子節點為空,或者只有一個節點的右子節點為空,則兩個二叉樹的結構不同,因此兩個二叉樹一定不同。
  • 如果兩個節點的子節點的結構相同,則將兩個節點的非空子節點分別加入兩個佇列,子節點加入佇列時需要注意順序,如果左右子節點都不為空,則先加入左子節點,後加入右子節點。

結果,如果迴圈結束的時候兩個佇列同時為空,那麼這兩個二叉樹相同,如果有一個不為空,那肯定不相同。

程式碼:

// 迭代
public boolean isSameTree(TreeNode p, TreeNode q) {
    if (p == null && q == null) {
        return true;
    } else if (p == null || q == null) {
        return false;
    } else if (p.val != q.val) {
        return false;
    } else {
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }
}

// 迴圈
public boolean isSameTree_1(TreeNode p, TreeNode q) {
    if (p == null && q == null) return true;
    if (p == null || q == null) return false;

    Queue<TreeNode> queue1 = new LinkedList<>();
    Queue<TreeNode> queue2 = new LinkedList<>();
    queue1.offer(p);
    queue2.offer(q);

    while (!queue1.isEmpty() && !queue2.isEmpty()) {
        TreeNode node1 = queue1.poll();
        TreeNode node2 = queue2.poll();

        if (node1.val != node2.val) return false;

        TreeNode left1 = node1.left, right1 = node1.right, left2 = node2.left, right2 = node2.right;

        if (left1 == null ^ left2 == null) return false;
        if (right1 == null ^ right2 == null) return false;

        if (left1 != null) queue1.offer(left1);
        if (right1 != null) queue1.offer(right1);
        if (left2 != null) queue2.offer(left2);
        if (right2 != null) queue2.offer(right2);
    }
    return queue1.isEmpty() && queue2.isEmpty();
}

結果我就不貼了,基本上答案區就這麼兩種解題方式,也沒其他能玩出花來的方式。