Leetcode99 恢復二叉搜尋樹

2021-08-22 02:39:32 字數 2050 閱讀 1021

第一次寫這個部落格以後我發現我理解錯了題目,但是我的問題更具有一般性,更複雜,所以文章就不改了

題目:只有兩個結點被錯誤的交換。

我的:有任意多個結點被錯誤的交換。

先分析題目:使用o(n)空間複雜度的解法很容易實現,那麼我們先看看很容易實現是怎實現的。

1、中序遍歷二叉樹,並將中序序列儲存在乙個陣列numbers中

2、對numbesr進行排序

3、中序遍歷二叉樹,並用numbers序列按遍歷順序覆蓋掉二叉樹中的每乙個值

此演算法即是我想到的空間複雜度為o(n)容易的解法

123的時間複雜度分別為o(n), o(nlogn), o(n),因此上述演算法時間複雜度為o(nlogn)

接下來,看一下使用常數空間怎麼解決這個問題。

先注意一點

void recovertree(treenode* root)
通過題目給的介面函式可以看出,是值傳遞。因此通過對原樹進行遍歷並重新構建乙個新樹,再把新樹根結點賦值給root的方法是不成立的,而且題目說明,樹的結構不發生改變,也能夠理解到,這個題目是要直接交換樹結點的值。

根據之前演算法1的啟發,其實要做的就是對二叉樹進行排序,使得其中序遍歷序列為有序序列即可。而中序遍歷能夠得到什麼?

能得到乙個按次序訪問的結點序列,如果每次訪問下乙個結點之前,都記錄乙個之前訪問的結點,那麼就可以得到一對相鄰結點。

然而思考的順序有些顛倒,設定乙個之前訪問的結點並不是突發奇想,而在於對排序演算法知識的積累。題目核心在於排序,因此需要思考排序演算法與此題目的關聯性,哪些排序演算法能夠比較容易套進來?常見的有選擇排序,氣泡排序,插入排序,快速排序。快速排序不考慮因為比較複雜,不論是選軸值和從兩端遍歷都不是那麼好實現。選擇排序每次需要從第k個位置去更新,也不太舒服。因此冒泡和插入排序是值得考慮的點。雖然是在用排除法,其實最開始就想到了氣泡排序,只是在總結時候強行加了這麼乙個思考方式,因為氣泡排序是比較相鄰元素,中序遍歷也比較容易得到乙個相鄰序列。

每次比較相鄰的訪問結點,並將數值較大的結點往後冒泡,最終就能得到有序的序列,在這個題目中,需要乙個改進的氣泡排序,當任何一次冒泡過程沒有發生元素交換,則冒泡過程結束,排序完成,否則就需要先統計樹的結點數目n,然後再進行n次冒泡,多次一舉。

具體演算法可以結合**理解:

class solution 

bool ok = true;

ok = ok && sorttree(root->left);

if (pre != null && root->val < pre->val)

pre = root;

ok = ok && sorttree(root->right);

return ok;

};do

while (!sorttree(root));}};

這裡用到了c++的lambda表示式,因為匿名引數的閉包特點,能夠將演算法封閉在函式內部,所以很優雅。效率仍未考知。

1、二叉排序樹的定義。左子樹結點都小於根結點的值,右子樹的結點都大於根結點的值,子樹也是二叉排序樹。

2、二叉排序樹可以通過中序遍歷得到有序序列,中序序列的逆序列可以得到降序序列。

3、基礎排序演算法的流程,特點。

4、遞迴函式的技巧,中序遍歷二叉搜尋樹過程中,得到序列需要乙個遞迴函式外的變數來保持索引過程。因此遞迴函式並不是完全封閉的。很多遞迴函式都用到了類似的技巧,通過訪問外部全域性或成員函式來獲得快捷訪問,也避免了遞迴函式引數傳遞過多的問題,但從封裝的角度上來說,這種做法是並不優雅的。

5、*lambda(非必要)

雖然通過演算法二解決了這個挑戰,也能成功ac,但氣泡排序的時間複雜度為o(n^2),並不是非常優秀,通過演算法一可以看到,這個題目的時間複雜度是可以達到理論最優的o(n*logn)的,因此該演算法也只能說解決了問題,而沒有較完美的解決問題,如果空間複雜度能控制在o(1),時間複雜度控制在o(n*logn),那麼應該是對這個題目乙個完美答卷了。感興趣的同學可以自己思考思考,是否能做的更好。

LeetCode 99 恢復二叉搜尋樹

3 1 2示例 2 輸入 3,1,4,null,null,2 3 1 4 2 輸出 2,1,4,null,null,3 2 1 4 3 高階 使用 o n 空間複雜度的解法很容易實現。你能想出乙個只使用常數空間的解決方案嗎?1.中序遍歷,儲存陣列 2.排序陣列 3.重新賦值,恢復二叉樹 includ...

LeetCode99 恢復二叉搜尋樹

二叉搜尋樹中的兩個節點被錯誤地交換。請在不改變其結構的情況下,恢復這棵樹。樹節點的定義 definition for a binary tree node.public class treenode treenode int val treenode int val,treenode left,tr...

leetcode 99恢復二叉搜尋樹

給你二叉搜尋樹的根節點 root 該樹中的兩個節點被錯誤地交換。請在不改變其結構的情況下,恢復這棵樹。高階 使用 o n 空間複雜度的解法很容易實現。你能想出乙個只使用常數空間的解決方案嗎?題目要求的是二叉搜尋樹,二叉搜尋樹有乙個特點,那就是有序,所以我們可以得知在中序遍歷二叉搜尋樹得到的序列是遞增...