[LeetCode] 897. Increasing Order Search Tree 遞增順序查找樹



Given a tree, rearrange the tree in in-order so that the leftmost node in the tree is now the root of the tree, and every node has no left child and only 1 right child. ``` Example 1: Input: [5,3,6,2,4,null,8,1,null,null,null,7,9]
  5
 / \
3   6

/ \
2 4 8
 / /
1 7 9

Output: [1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]

1

  2

  3

  4

  5

  6

  7

  8

9

Note:

1.  The number of nodes in the given tree will be between 1 and 100.
2.  Each node will have a unique integer value from 0 to 1000.


<br>
這道題給了一棵二叉樹,讓我們對其進行重排序,使得最左結點變為根結點,而且整個樹不能有左子結點,如題目中的例子所示,排序后的結果是一條向右下方延伸的直線。如果我們仔細觀察題目中的例子,可以發現遍歷順序其實是 左->根->右,就是中序遍歷的順序,雖然題目中沒說是二叉搜索樹,但這並不影響我們進行中序遍歷。我們先從最簡單的例子開始分析,當 root 為空時,直接返回空,當 root 沒有左右子結點時,也是直接返回 root。當 root 只有一個左子結點時,我們此時要把其左子結點變為根結點,將原來的根結點變成其原來的左子結點的右子結點。但是如果 root 只有一個右子結點,還是保持原來的順序不變,而若 root 同時具有左右子結點的話,還是要將左子結點變為根結點,然后把之前的根結點連到右子結點上,之前的右子結點還連在之前的根結點上,這個不用改變。我們可以發現,最麻煩的就是左子結點了,需要和其根結點交換位置,所以對於每個結點,我們需要知道其父結點的位置,那么就在遞歸函數的參數中傳入一個 pre 結點,再對左右子結點調用遞歸函數時,都將其下一個要連接的結點傳入,這個 pre 結點可能是當前結點或者當前結點的父結點。

在遞歸函數中,首先判空,若當前結點為空的話,直接返回 pre 結點,因為到空結點的時候,說明已經遍歷到葉結點的下方了,那么 pre 就是這個葉結點了。由於是中序遍歷,所以要先對左子結點調用遞歸函數,將返回值保存到一個新的結點 res 中,表示的意義是此時 node 的左子樹已經全部捋直了,而且根結點就是 res,而且 node 結點本身也被連到了捋直后的左子樹下,即此時左子結點和根結點已經完成了交換位子,當然要斷開原來的連接,所以將 node->left 賦值為 nullptr。然后再對 node 的右子結點調用遞歸函數,注意此時的 pre 不能傳入 node 本身,而是要傳 node 結點的 pre 結點,這是因為右子結點后面要連接的是 node 的父結點,比如兌入下面這例子:

4

/
2
/
1 3


當運行到結點3的時候,pre 應該帶入的是結點4,這樣就可以把結點4連到結點3的右下方,從而正確的捋直,參見代碼如下:

<br>
解法一:

class Solution {
public:
TreeNode* increasingBST(TreeNode* root) {
return helper(root, nullptr);
}
TreeNode* helper(TreeNode* node, TreeNode* pre) {
if (!node) return pre;
TreeNode* res = helper(node->left, node);
node->left = nullptr;
node->right = helper(node->right, pre);
return res;
}
};



<br>
我們也可以采用中序遍歷的迭代形式,使用棧來輔助。由於根結點可能會產生變化,所以我們需要一個 dummy 結點,還需要一個 pre 結點。在 while 循環中,先找到最左結點,把路徑上的所有結點都壓入棧,然后取出棧頂元素,將其連到 pre 的右子結點上,並將 pre 更新為其右子結點,然后斷開棧頂元素的左子結點連接,並將其移動到右子結點上,並繼續循環,最終返回 dummy 的右子結點即可,參見代碼如下:

<br>
解法二:


class Solution {
public:
TreeNode* increasingBST(TreeNode* root) {
TreeNode *dummy = new TreeNode(-1), pre = dummy;
stack<TreeNode
> st;
while (root || !st.empty()) {
while (root) {
st.push(root);
root = root->left;
}
root = st.top(); st.pop();
pre->right = root;
pre = pre->right;
root->left = nullptr;
root = root->right;
}
return dummy->right;
}
};


<br>
Github 同步地址:

<https://github.com/grandyang/leetcode/issues/897>


<br>
參考資料:

<https://leetcode.com/problems/increasing-order-search-tree/>


<https://leetcode.com/problems/increasing-order-search-tree/discuss/251290/C%2B%2B-short-iterative>


<https://leetcode.com/problems/increasing-order-search-tree/discuss/165885/C%2B%2BJavaPython-Self-Explained-5-line-O(N)>


<br>
[LeetCode All in One 題目講解匯總(持續更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM