這次給大家帶來的是一道關於樹結構的題——相同的樹。該題是一道難度爲簡單的題目,考察的是對樹結構進行遍歷的理解。
描述
給定兩個二叉樹,編寫一個函數來檢驗它們是否相同。
如果兩個樹在結構上相同,並且節點具有相同的值,則認爲它們是相同的。
示例
示例1:
輸入:
[1,2,3]
[1,2,3]
輸出:
true
圖解:
1 1
/ \ / \
2 3 2 3
示例2:
輸入:
[1,2]
[1,null,2]
輸出:
false
圖解:
1 1
/ \
2 2
示例3:
輸入:
[1,2,1]
[1,1,2]
輸出:
false
圖解:
1 1
/ \ / \
2 1 1 2
解法一
比較容易想到且實現的一種解法就是利用遞歸進行實現。每次調用IsSameTree
方法時判斷當前兩個結點是否相同(需要處理爲空的情況),若二者的值不同則不爲相同的樹;若二者的值相同,則通過IsSameTree
方法對子結點繼續進行判斷。
public bool IsSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null)
{
return true;
}
else if (p == null || q == null)
{
return false;
}
return p.val == q.val && IsSameTree(p.left, q.left) && IsSameTree(p.right, q.right);
}
遞歸法對每個結點只訪問一次,時間複雜度爲O(N),且不需要輔助的內存空間,但需要額外的函數調用開銷。
解法二
同樣,我們也可以使用迭代的方法實現該題。在對樹使用迭代法進行遍歷時,需要使用額外的輔助空間存放尚未遍歷到的結點,這裏我們使用了兩個隊列做這個工作。
在開始時,要先把樹的根結點入隊。在每次迭代的過程中需要判斷當前結點的值是否相同(同樣也要處理爲空的情況),若二者的值不同則不是相同的樹;若二者的值相同則將子結點入隊,繼續進行下一輪迭代。
public bool IsSameTree(TreeNode p, TreeNode q) {
Queue<TreeNode> pQueue = new Queue<TreeNode>();
Queue<TreeNode> qQueue = new Queue<TreeNode>();
pQueue.Enqueue(p);
qQueue.Enqueue(q);
while (pQueue.Count > 0 || qQueue.Count > 0)
{
TreeNode pNode = pQueue.Dequeue();
TreeNode qNode = qQueue.Dequeue();
if (pNode == null && qNode == null)
{
continue;
}
else if (pNode == null || qNode == null || pNode.val != qNode.val)
{
return false;
}
pQueue.Enqueue(pNode.left);
pQueue.Enqueue(pNode.right);
qQueue.Enqueue(qNode.left);
qQueue.Enqueue(qNode.right);
}
return true;
}
使用迭代法也只對每個結點訪問一次,時間複雜度爲O(N),另外需要對應的輔助存儲空間。在最優的情況下,空間複雜度爲O(log(N)),最壞情況下爲O(N)。
結束語
對於上述的示例有多種解法,如使用迭代法時可以只使用一個額外的輔助隊列存放結點,但爲了能讓大家快速理解便未進行相應的優化。
今天的內容就到這裏啦,我們下週再見👋~
歡迎大家關注我的公衆號“風紙”,或是掃下面的二維碼關注👇