1. 程式人生 > >[leetcode] Increasing Order Search Tree

[leetcode] Increasing Order Search Tree

節點 println scrip ear each lin 新的 ray 想法

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.

分析:題目翻譯一下:根據中序遍歷,調整二叉樹,變成所有的節點都在右子樹上。 思路一:第一個想法,先對樹進行中序遍歷,保存中序遍歷的結果;然後生成一個新樹,按照上邊的順序連接起來。 代碼如下:
 1 class Solution {
 2     List<Integer> list = new ArrayList<>();
3 public TreeNode increasingBST(TreeNode root){ 4 zxbl(root); 5 TreeNode head = new TreeNode(0); 6 TreeNode node = head; 7 for ( int n : list ){ 8 //System.out.println(n); 9 head.right = new TreeNode(n); 10 head = head.right;
11 } 12 return node.right; 13 } 14 private void zxbl(TreeNode root) { 15 if ( root == null ) return; 16 zxbl(root.left); 17 list.add(root.val); 18 zxbl(root.right); 19 } 20 }

運行時間73ms,顯然是一個不太好的方法。

思路二:延續上面的思路,之前list中保存的是root 的值,如果直接保存root是不是更快一點呢?

代碼如下:

 1 class Solution {
 2     List<TreeNode> list = new ArrayList<>();
 3     public TreeNode increasingBST(TreeNode root){
 4         zxbl(root);
 5         TreeNode head = new TreeNode(0);
 6         TreeNode node = head;
 7         for ( TreeNode n : list ){
 8             head.right = n;
 9             head = head.right;
10             head.left=null;
11             
12         }
13         return node.right;
14     }
15     private void zxbl(TreeNode root) {
16         if ( root == null ) return;
17         zxbl(root.left);
18         list.add(root);
19         zxbl(root.right);
20     }
21 }

運行時間36ms,擊敗74.29%。這裏一定要註意紅色部分,要給左指針附上null,否則會報錯。

思路三:下面想想如何去掉list整個限制呢?也就是在中序遍歷的過程中,就實現鏈接。

代碼如下:

 1 class Solution {
 2     TreeNode head;
 3     public TreeNode increasingBST(TreeNode root){
 4         if ( root == null ) return null;
 5         TreeNode node = new TreeNode(0);
 6         head = node;
 7         zxbl(root);
 8         return node.right;
 9     }
10     private void zxbl(TreeNode root) {
11         if ( root == null ) return;
12         zxbl(root.left);
13         root.left=null;
14         head.right = root;
15         head = root;
16         zxbl(root.right);
17     }
18 }

運行時間34ms,擊敗82.92%。這裏要註意13行紅色代碼,我的理解是:這裏的root就已經是左孩子為null,右孩子不變的一個節點,然後鏈接到head上。

我又嘗試了如何劃歸到上面list版本的形式,代碼如下:

 1 class Solution {
 2     TreeNode head;
 3     public TreeNode increasingBST(TreeNode root){
 4         if ( root == null ) return null;
 5         TreeNode node = new TreeNode(0);
 6         head = node;
 7         zxbl(root);
 8         return node.right;
 9     }
10     private void zxbl(TreeNode root) {
11         if ( root == null ) return;
12         zxbl(root.left);
13         
14         head.right = root;
15         head = head.right;
16         head.left=null;
17         
18         zxbl(root.right);
19     }
20 }

基本沒什麽太大的變化,主要這裏就是先下移,然後令左孩子為null;上面的是先令左孩子為null,再下移。一樣的。

思路四:雖然上面的解法可以獲得答案,但是題目中提示:對樹進行rearrange,而不是去新建一棵樹。所以下面就是尋找一個新的方法,對原來的樹進行操作。

附上discuss中大神的解法:

 1     public TreeNode increasingBST(TreeNode root) {
 2         return helper(root, null);
 3     }
 4 
 5     public TreeNode increasingBST(TreeNode root, TreeNode tail) {
 6         if (root == null) return tail;
 7         TreeNode res = increasingBST(root.left, root);
 8         root.left = null;
 9         root.right = increasingBST(root.right, tail);
10         return res;
11     }

這個方法比較難以理解,我盡量理解並且講明白:

這裏要註意一點,它的整個思路就是res = inorder(root.left) + root + inorder(root.right)。

關鍵來看一下tail這個變量,tail保存的是比當前節點最近最大的一個節點,而且僅僅在左子樹的遍歷的時候賦值。比如上面的案例,剛開始就已知遍歷到1,這個時候tail指向2,然後回到父節點2,tail指向3,因為2沒有右孩子,所以指向父節點3,這個時候tail指向5,然後遍歷3的右孩子4,然後回到5。在這裏就鏈接好了1-2-3-4-5。在遍歷右子樹時,tail為null,最後鏈接在9上。

感覺過程太玄學,不容易理解,還是之前的方法更形象一點。

[leetcode] Increasing Order Search Tree