[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.html

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:node

  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.



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

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

4
   /
  2
 / \
1   3

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



解法一:code

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;
    }
};



咱們也能夠採用中序遍歷的迭代形式,使用棧來輔助。因爲根結點可能會產生變化,因此咱們須要一個 dummy 結點,還須要一個 pre 結點。在 while 循環中,先找到最左結點,把路徑上的全部結點都壓入棧,而後取出棧頂元素,將其連到 pre 的右子結點上,並將 pre 更新爲其右子結點,而後斷開棧頂元素的左子結點鏈接,並將其移動到右子結點上,並繼續循環,最終返回 dummy 的右子結點便可,參見代碼以下:htm



解法二:blog

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;
    }
};



Github 同步地址:排序

https://github.com/grandyang/leetcode/issues/897遞歸



參考資料:

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)



LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索