Showing posts with label 二叉树. Show all posts
Showing posts with label 二叉树. Show all posts

Monday, August 7, 2017

[Leetcode] Binary Tree Vertical Order Traversal, Solution

Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column).
If two nodes are in the same row and column, the order should be from left to right.
Examples:
  1. Given binary tree [3,9,20,null,null,15,7],
       3
      /\
     /  \
     9  20
        /\
       /  \
      15   7
    
    return its vertical order traversal as:
    [
      [9],
      [3,15],
      [20],
      [7]
    ]
    
  2. Given binary tree [3,9,8,4,0,1,7],
         3
        /\
       /  \
       9   8
      /\  /\
     /  \/  \
     4  01   7
    
    return its vertical order traversal as:
    [
      [4],
      [9],
      [3,0,1],
      [8],
      [7]
    ]
    
  3. Given binary tree [3,9,8,4,0,1,7,null,null,null,2,5] (0's right child is 2 and 1's left child is 5),
         3
        /\
       /  \
       9   8
      /\  /\
     /  \/  \
     4  01   7
        /\
       /  \
       5   2
    
    return its vertical order traversal as:
    [
      [4],
      [9,5],
      [3,0,1],
      [8,2],
      [7]
    ]
    
[Thoughts]
这题挺有意思的。其实就是做一个按层遍历(http://fisherlei.blogspot.com/2013/01/leetcode-binary-tree-level-order.html),只不过在遍历的过程中,同时对于每一个节点记录其vertical index,放到map中去做统计。

[Code]

1:  /**  
2:   * Definition for a binary tree node.  
3:   * struct TreeNode {  
4:   *   int val;  
5:   *   TreeNode *left;  
6:   *   TreeNode *right;  
7:   *   TreeNode(int x) : val(x), left(NULL), right(NULL) {}  
8:   * };  
9:   */  
10:  class Solution {  
11:  public:  
12:    map<int, vector<int>> record;  
13:      
14:    vector<vector<int>> verticalOrder(TreeNode* root) {  
15:      seqOrder(root);  
16:      vector<vector<int>> result;  
17:      for(auto rec : record) {  
18:        result.push_back(rec.second);  
19:      }  
20:      return result;  
21:    }  
22:      
23:    void seqOrder(TreeNode* root) {  
24:      queue<TreeNode*> visit;  
25:      queue<int> vertical_index;  
26:        
27:      if(root == NULL) return;  
28:      visit.push(root);  
29:      vertical_index.push(0);  
30:      while(visit.size() >0) {  
31:        TreeNode* node = visit.front();  
32:        int cur_in = vertical_index.front();  
33:        visit.pop();  
34:        vertical_index.pop();  
35:          
36:        record[cur_in].push_back(node->val);  
37:          
38:        if(node->left != NULL) {  
39:          visit.push(node->left);  
40:          vertical_index.push(cur_in -1);  
41:        }  
42:          
43:        if(node->right != NULL) {  
44:          visit.push(node->right);  
45:          vertical_index.push(cur_in +1);  
46:        }  
47:      }   
48:    }  
49:  };  



Thursday, July 20, 2017

[Leetcode] Serialize and Deserialize Binary Tree, Solution

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
For example, you may serialize the following tree
    1
   / \
  2   3
     / \
    4   5
as "[1,2,3,null,null,4,5]", just the same as how LeetCode OJ serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.


[Thoughts]

这题纯粹是一道实现题,没有难点。看Code。



[Code]

1:  /**  
2:   * Definition for a binary tree node.  
3:   * struct TreeNode {  
4:   *   int val;  
5:   *   TreeNode *left;  
6:   *   TreeNode *right;  
7:   *   TreeNode(int x) : val(x), left(NULL), right(NULL) {}  
8:   * };  
9:   */  
10:  class Codec {  
11:  public:  
12:    
13:    // Encodes a tree to a single string.  
14:    string serialize(TreeNode* root) {  
15:      stringstream ss;  
16:      serializeImpl(root, ss);  
17:      return ss.str();  
18:    }  
19:    
20:    // Decodes your encoded data to tree.  
21:    TreeNode* deserialize(string data) {  
22:      std::istringstream ss(data);  
23:      return deserializeImpl(ss);  
24:    }  
25:      
26:    void serializeImpl(TreeNode* root, stringstream& ss) {  
27:      if(root == NULL) {  
28:        ss<<"#,";  
29:        return;  
30:      }  
31:        
32:      ss << root->val << ",";  
33:      serializeImpl(root->left, ss);  
34:      serializeImpl(root->right, ss);  
35:    }  
36:      
37:    TreeNode* deserializeImpl(istringstream & ss) {  
38:      std::string token;  
39:    
40:      std::getline(ss, token, ',');  
41:        
42:      if(token == "#") {  
43:        return NULL;  
44:      }  
45:        
46:      TreeNode* root = new TreeNode(stoi(token));  
47:        
48:      root->left = deserializeImpl(ss);  
49:      root->right = deserializeImpl(ss);  
50:      return root;  
51:    }  
52:      
53:      
54:  };  
55:    
56:  // Your Codec object will be instantiated and called as such:  
57:  // Codec codec;  
58:  // codec.deserialize(codec.serialize(root));  


Friday, October 16, 2015

[Leetcode] Binary Tree Paths, Solution

Given a binary tree, return all root-to-leaf paths.
For example, given the following binary tree:
   1
 /   \
2     3
 \
  5
All root-to-leaf paths are:
["1->2->5", "1->3"]

[Thought]
这个主要就是实现题。对树进行深度遍历,在遍历的过程中保存访问节点,当遍历到叶节点的时候,打印出来路径即可。

[Code]
1:  class Solution {  
2:  public:  
3:    vector<string> binaryTreePaths(TreeNode* root) {  
4:      vector<string> paths;  
5:      vector<int> nodes;  
6:      getAllPaths(root, nodes, paths);       
7:      return paths;  
8:    }  
9:    void getAllPaths(TreeNode* node, vector<int>& nodes,vector<string>& paths) {  
10:      if(node == NULL) {  
11:        return;  
12:      }  
13:      if(node->left== NULL && node->right == NULL) {  
14:        stringstream ss;  
15:        for(int i =0; i< nodes.size(); i++) {  
16:          ss << nodes[i] << "->";  
17:        }  
18:        ss << node->val;  
19:        paths.push_back(ss.str());  
20:        return;  
21:      }  
22:      nodes.push_back(node->val);  
23:      getAllPaths(node->left, nodes, paths);  
24:      getAllPaths(node->right, nodes, paths);  
25:      nodes.pop_back();  
26:    }  
27:  };  

Github: https://github.com/codingtmd/leetcode/blob/master/src/Binary%20Tree%20Paths.cpp

Saturday, March 23, 2013

[LeetCode] Path Sum, Solution


Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
For example:
Given the below binary tree and sum = 22,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \      \
        7    2      1
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.
» Solve this problem

[Thoughts]
二叉树遍历。遍历过程中累加节点值,当到达任意叶节点的时候,进行判断。


[Code]
1:       bool hasPathSum(TreeNode *root, int sum) {  
2:            return hasPathSum(root, 0, sum);      
3:       }  
4:       bool hasPathSum(TreeNode *root, int sum, int target) {  
5:            if(root == NULL) return false;  
6:            sum += root->val;  
7:            if(root->left == NULL && root->right == NULL) //leaf  
8:            {  
9:                 if(sum == target)  
10:                      return true;  
11:                 else  
12:                      return false;  
13:            }  
14:            return hasPathSum(root->left, sum, target)   
15:                   || hasPathSum(root->right, sum, target);      
16:       }  











Friday, March 22, 2013

[Interview] Serialize and De-serialize a tree

A very frequent interview question. Suppose you have a tree, how could you serialize it to file and revert it back?


for example,

                                               1
                                         /               \
                                        2                 3
                                             \          /    
                                             4        5    
                                          /       \
                                         6        7

[Thoughts]
一个比较简单直接的做法是,通过前序遍历来做,把所有空节点当做“#”来标示。那么这棵树可以表示为

                                               1
                                         /               \
                                        2                 3
                                     /       \          /      \
                                  #         4        5       #
                                          /       \
                                         6        7
                                     /      \     /    \
                                    #      #    #     #

那么前序遍历的结果就是: {'1','2','#','4','6','#','#','7','#','#','3','5','#','#','#'}; 代码如下:


void Serialize(TreeNode * node, vector<char> &output)
{
       if(node == NULL)
       {
             output.push_back('#');
             return;
       }

       output.push_back(node->val + '0');
       Serialize(node->left, output);
       Serialize(node->right, output);
}

而反序列化的代码也就是:

TreeNode *Deserialize(vector<char> output, int &index)
{
       if(index > output.size() || output[index] == '#') return NULL;

       TreeNode *node = new TreeNode(output[index] -'0');
       index ++;
       node->left = Deserialize(output, index);
       index++;
       node->right = Deserialize(output, index);
       return node;
}



这里只能通过前序遍历来做,中序及后序是行不通的。原因很简单,除了前序以外,其他遍历方式没办法找出头结点。

除了常规的三种遍历方式意外, 另一种可行的方法就是按层来遍历,同样可行。










Thursday, March 21, 2013

[LeetCode] Same Tree, Solution


Given two binary trees, write a function to check if they are equal or not.
Two binary trees are considered equal if they are structurally identical and the nodes have the same value.
» Solve this problem


[Thoughts]
递归判断左右子树是否相等。


[Code]
1:    bool isSameTree(TreeNode *p, TreeNode *q) {  
2:      if(!p && !q) return true;  
3:      if(!p || !q) return false;  
4:      return (p->val == q->val) &&  
5:           isSameTree(p->left, q->left) &&   
6:           isSameTree(p->right, q->right);      
7:    }  

Wednesday, March 20, 2013

[LeetCode] Unique Binary Search Trees II, Solution


Given n, generate all structurally unique BST's (binary search trees) that store values 1...n.
For example,
Given n = 3, your program should return all 5 unique BST's shown below.
   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem


[Thoughts]
分析请参看http://fisherlei.blogspot.com/2013/03/leetcode-unique-binary-search-trees.html
思路是一致的。划分左右子树,然后递归构造。

[Code]
1:       vector<TreeNode *> generateTrees(int n) {   
2:            if(n ==0) return generate(1,0);  
3:            return generate(1, n);  
4:       }       
5:       vector<TreeNode *> generate(int start, int end)  
6:       {  
7:            vector<TreeNode *> subTree;  
8:            if(start>end)  
9:            {  
10:                 subTree.push_back(NULL);  
11:                 return subTree;  
12:            }  
13:            for(int i =start; i<=end; i++)  
14:            {  
15:                 vector<TreeNode*> leftSubs = generate(start, i-1);  
16:                 vector<TreeNode*> rightSubs = generate(i+1, end);  
17:                 for(int j = 0; j< leftSubs.size(); j++)  
18:                 {  
19:                      for(int k=0; k<rightSubs.size(); k++)  
20:                      {  
21:                           TreeNode *node = new TreeNode(i);  
22:                           node->left = leftSubs[j];  
23:                           node->right = rightSubs[k];  
24:                           subTree.push_back(node);  
25:                      }  
26:                 }  
27:            }  
28:            return subTree;  
29:       }      


[Note]
写完第一个版本之后,立即发现一个严重的问题。上面的function存在大量的对象拷贝,因为所有变量都是在栈上开辟,所以返回值的时候都需要通过拷贝构造函数来重构vector,面试中这个疏忽是不应该的。

修改版,这里应该用指针及堆来存储变量。
1:       vector<TreeNode *> generateTrees(int n) {   
2:            if(n ==0) return *generate(1,0);  
3:            return *generate(1, n);  
4:       }  
5:       vector<TreeNode *>* generate(int start, int end)  
6:       {  
7:            vector<TreeNode *> *subTree = new vector<TreeNode*>();  
8:            if(start>end)  
9:            {  
10:                 subTree->push_back(NULL);  
11:                 return subTree;  
12:            }  
13:            for(int i =start; i<=end; i++)  
14:            {  
15:                 vector<TreeNode*> *leftSubs = generate(start, i-1);  
16:                 vector<TreeNode*> *rightSubs = generate(i+1, end);  
17:                 for(int j = 0; j< leftSubs->size(); j++)  
18:                 {  
19:                      for(int k=0; k<rightSubs->size(); k++)  
20:                      {  
21:                           TreeNode *node = new TreeNode(i);  
22:                           node->left = (*leftSubs)[j];  
23:                           node->right = (*rightSubs)[k];  
24:                           subTree->push_back(node);  
25:                      }  
26:                 }  
27:            }  
28:            return subTree;  
29:       }      


[LeetCode] Unique Binary Search Trees, Solution


Given n, how many structurally unique BST's (binary search trees) that store values 1...n?
For example,
Given n = 3, there are a total of 5 unique BST's.
   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3
» Solve this problem

[Thoughts]
这题想了好久才想清楚。其实如果把上例的顺序改一下,就可以看出规律了。
 1                1                      2                       3             3
    \                 \                 /      \                  /              /
      3               2              1       3               2             1
    /                   \                                       /                  \
 2                       3                                   1                    2

比如,以1为根的树有几个,完全取决于有二个元素的子树有几种。同理,2为根的子树取决于一个元素的子树有几个。以3为根的情况,则与1相同。

定义Count[i] 为以[0,i]能产生的Unique Binary Tree的数目,

如果数组为空,毫无疑问,只有一种BST,即空树,
Count[0] =1

如果数组仅有一个元素{1},只有一种BST,单个节点
Count[1] = 1

如果数组有两个元素{1,2}, 那么有如下两种可能
1                       2
  \                    /
    2                1
Count[2] = Count[0] * Count[1]   (1为根的情况)
                  + Count[1] * Count[0]  (2为根的情况。

再看一遍三个元素的数组,可以发现BST的取值方式如下:
Count[3] = Count[0]*Count[2]  (1为根的情况)
               + Count[1]*Count[1]  (2为根的情况)
               + Count[2]*Count[0]  (3为根的情况)

所以,由此观察,可以得出Count的递推公式为
Count[i] = ∑ Count[0...k] * [ k+1....i]     0<=k<i-1
问题至此划归为一维动态规划。

[Code]
1:       int numTrees(int n) {  
2:            vector<int> count(n+1, 0);  
3:            count[0] =1;  
4:            count[1] =1;  
5:            for(int i =2; i<=n; i++)  
6:            {  
7:                 for(int j =0; j<i; j++)  
8:                 {  
9:                      count[i] += count[j]*count[i-j-1];   
10:                 }  
11:            }  
12:            return count[n];  
13:       }  


[Note]
这是很有意思的一个题。刚拿到这题的时候,完全不知道从那下手,因为对于BST是否Unique,很难判断。最后引入了一个条件以后,立即就清晰了,即
当数组为 1,2,3,4,.. i,.. n时,基于以下原则的BST建树具有唯一性:
以i为根节点的树,其左子树由[0, i-1]构成, 其右子树由[i+1, n]构成。



Saturday, February 2, 2013

[Google] Inorder Successor in Binary Search Tree, Solution


In Binary Tree, Inorder successor of a node is the next node in Inorder traversal of the Binary Tree. Inorder Successor is NULL for the last node in Inoorder traversal.
In Binary Search Tree, Inorder Successor of an input node can also be defined as the node with the smallest key greater than the key of input node. So, it is sometimes important to find next node in sorted order.

In the above diagram, inorder successor of 8 is 10, inorder successor of 10 is 12 and inorder successor of 14 is 20.
Method 1 (Uses Parent Pointer)
In this method, we assume that every node has parent pointer.
The Algorithm is divided into two cases on the basis of right subtree of the input node being empty or not.
Input: node, root // node is the node whose Inorder successor is needed.
output: succ // succ is Inorder successor of node.
1) If right subtree of node is not NULL, then succ lies in right subtree. Do following.
Go to right subtree and return the node with minimum key value in right subtree.
2) If right sbtree of node is NULL, then succ is one of the ancestors. Do following.
Travel up using the parent pointer until you see a node which is left child of it’s parent. The parent of such a node is the succ.
Implementation
Note that the function to find InOrder Successor is highlighted (with gray background) in below code.
1:  #include <stdio.h>  
2:  #include <stdlib.h>  
3:  /* A binary tree node has data, pointer to left child  
4:    and a pointer to right child */  
5:  struct node  
6:  {  
7:    int data;  
8:    struct node* left;  
9:    struct node* right;  
10:    struct node* parent;  
11:  };  
12:  struct node * minValue(struct node* node);  
13:  struct node * inOrderSuccessor(struct node *root, struct node *n)  
14:  {  
15:   // step 1 of the above algorithm  
16:   if( n->right != NULL )  
17:    return minValue(n->right);  
18:   // step 2 of the above algorithm  
19:   struct node *p = n->parent;  
20:   while(p != NULL && n == p->right)  
21:   {  
22:     n = p;  
23:     p = p->parent;  
24:   }  
25:   return p;  
26:  }  
27:  /* Given a non-empty binary search tree, return the minimum data   
28:    value found in that tree. Note that the entire tree does not need  
29:    to be searched. */  
30:  struct node * minValue(struct node* node) {  
31:   struct node* current = node;  
32:   /* loop down to find the leftmost leaf */  
33:   while (current->left != NULL) {  
34:    current = current->left;  
35:   }  
36:   return current;  
37:  }  
Time Complexity: O(h) where h is height of tree.


Method 2 (Don't Use Parent Pointer)
Inorder travel the tree and
1) If current visit node is target node,  mark the indicator as true.
2) If indicator is true, print the node and return.

Implementation
1:  struct node * inOrderSuccessor(struct node *n, struct node* target, bool& indicator)  
2:  {  
3:   if( n== NULL )  
4:    return NULL;  
5:   if(indicator) return n;  
6:   if(n == target) { indicator = true; return;}  
7:   node* left = inOrderSuccessor(n->left, target, indicator);  
8:   node * right =inOrderSuccessor(n->right, target, indicator);  
9:   if(left != NULL) return left;  
10:   if(right!= NULL) return right;  
11:   return NULL;  
12:  }  

Sunday, January 27, 2013

[LeetCode] Convert Sorted List to Binary Search Tree, Solution


Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
» Solve this problem

[Thoughts]
It is similar with "Convert Sorted Array to Binary Search Tree". But the difference here is we have no way to random access item in O(1).

If we build BST from array, we can build it from top to bottom, like
1. choose the middle one as root,
2. build left sub BST
3. build right sub BST
4. do this recursively.

But for linked list, we can't do that because Top-To-Bottom are heavily relied on the index operation.
There is a smart solution to provide an Bottom-TO-Top as an alternative way, http://leetcode.com/2010/11/convert-sorted-list-to-balanced-binary.html

With this, we can insert nodes following the list’s order. So, we no longer need to find the middle element, as we are able to traverse the list while inserting nodes to the tree.

[Code]
1:    TreeNode *sortedListToBST(ListNode *head) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      int len =0;  
5:      ListNode *p = head;  
6:      while(p)  
7:      {  
8:        len++;  
9:        p = p->next;  
10:      }  
11:      return BuildBST(head, 0, len-1);  
12:    }  
13:    TreeNode* BuildBST(ListNode*& list, int start, int end)  
14:    {  
15:      if (start > end) return NULL;  
16:      int mid = (start+end)/2;   //if use start + (end - start) >> 1, test case will break, strange!
17:      TreeNode *leftChild = BuildBST(list, start, mid-1);  
18:      TreeNode *parent = new TreeNode(list->val);  
19:      parent->left = leftChild;  
20:      list = list->next;  
21:      parent->right = BuildBST(list, mid+1, end);  
22:      return parent;  
23:    }  


Thursday, January 17, 2013

[LeetCode] Binary Tree Level Order Traversal Solution


Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).
For example:
Given binary tree {3,9,20,#,#,15,7},
    3
   / \
  9  20
    /  \
   15   7
return its level order traversal as:
[
  [3],
  [9,20],
  [15,7]
]
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem

[Thoughts]
Two ways to resolve this problem:
1. Breadth first search
Initial an int variable to track the node count in each level and print level by level. And here need a QUEUE as a helper.
2. Depth first search
Rely on the recursion. Decrement level by one as you advance to the next level. When level equals 1, you’ve reached the given level and output them.
The cons is, DFS will revisit the node, which make it less efficient than BFS.

[Code]
BFS solution
1:    vector<vector<int> > levelOrder(TreeNode *root) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      vector<vector<int> > result;  
5:      vector<TreeNode*> sta;  
6:      if(root == NULL) return result;  
7:      sta.push_back(root);  
8:      int nextLevCou=1;  
9:      int index=0;  
10:      while(index < sta.size())  
11:      {  
12:        int curLevCou = nextLevCou;  
13:        nextLevCou =0;  
14:        vector<int> level;  
15:        for(int i =index; i< index+curLevCou; i++)  
16:        {  
17:          root = sta[i];          
18:          level.push_back(root->val);  
19:          if(root->left!=NULL)  
20:          {  
21:            sta.push_back(root->left);  
22:            nextLevCou++;  
23:          }  
24:          if(root->right!=NULL)  
25:          {  
26:            sta.push_back(root->right);  
27:            nextLevCou++;  
28:          }  
29:        }  
30:        result.push_back(level);  
31:        index = index +curLevCou;  
32:      }  
33:      return result;  
34:    }  


DFS solution
1:    vector<vector<int> > levelOrder(TreeNode *root) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function      
4:      vector<vector<int> > output;  
5:      if(!root) return output;  
6:      vector<int> oneLine;  
7:      bool hasNextLevel=true;  
8:      int currentLevel =1;  
9:      while(hasNextLevel)  
10:      {  
11:        hasNextLevel = false;  
12:        LevelTravel(root, currentLevel, hasNextLevel, oneLine);  
13:        output.push_back(oneLine);  
14:        currentLevel ++;  
15:        oneLine.clear();  
16:      }  
17:      return output;  
18:    }  
19:    void LevelTravel(  
20:      TreeNode* node,   
21:      int level,  
22:      bool& hasNextLevel,  
23:      vector<int>& result)  
24:    {  
25:      if(!node) return;  
26:      if(level ==1)  
27:      {  
28:        result.push_back(node->val);  
29:        if(node->left || node->right)  
30:          hasNextLevel = true;  
31:        return;  
32:      }  
33:      else  
34:      {  
35:        LevelTravel(node->left, level-1, hasNextLevel, result);  
36:        LevelTravel(node->right, level-1, hasNextLevel, result);  
37:      }  
38:    }  


Update 1/12/2014 
BFS的code太啰嗦,用两个循环虽然看着清楚了,但是code不够漂亮,改一下。

1:    vector<vector<int> > levelOrder(TreeNode *root) {  
2:      vector<vector<int> > result;  
3:      if(root == NULL) return result;  
4:      queue<TreeNode*> nodeQ;  
5:      nodeQ.push(root);  
6:      int nextLevelCnt=0, currentLevelCnt=1;  
7:      vector<int> layer;  
8:      int visitedCnt=0;  
9:      while(nodeQ.size() != 0)  
10:      {  
11:        TreeNode* node = nodeQ.front();  
12:        nodeQ.pop();  
13:        visitedCnt++;  
14:        layer.push_back(node->val);  
15:        if(node->left != NULL)  
16:        {  
17:          nodeQ.push(node->left);  
18:          nextLevelCnt++;  
19:        }  
20:        if(node->right != NULL)  
21:        {  
22:          nodeQ.push(node->right);  
23:          nextLevelCnt++;  
24:        }  
25:        if(visitedCnt == currentLevelCnt)  
26:        {  
27:          visitedCnt =0;  
28:          currentLevelCnt = nextLevelCnt;  
29:          nextLevelCnt=0;  
30:          result.push_back(layer);  
31:          layer.clear();  
32:        }  
33:      }  
34:      return result;  
35:    }  







Wednesday, January 16, 2013

[LeetCode] Binary Tree Inorder Traversal Solution


Given a binary tree, return the inorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3},
   1
    \
     2
    /
   3
return [1,3,2].
Note: Recursive solution is trivial, could you do it iteratively?
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem

[Thoughts]
For recursion version, it's very easy to write.

But for iterative version, we need a stack to help.


[Code]
Recursion version
1:    vector<int> inorderTraversal(TreeNode *root) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      vector<int> result;  
5:      inorderTra(root, result);  
6:      return result;  
7:    }  
8:    void inorderTra(TreeNode* node, vector<int> &result)  
9:    {  
10:      if(node == NULL)  
11:      {        
12:        return;  
13:      }  
14:      inorderTra(node->left, result);  
15:      result.push_back(node->val);      
16:      inorderTra(node->right, result);  
17:    }  

Iteration version
1:    vector<int> inorderTraversal(TreeNode *root) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      vector<TreeNode*> sta;  
5:      vector<int> result;  
6:      if(root == NULL) return result;  
7:      TreeNode* node =root;  
8:      while(sta.size()>0 || node!=NULL)  
9:      {  
10:        while(node!=NULL)  
11:        {  
12:          sta.push_back(node);  
13:          node = node->left;  
14:        }  
15:        node= sta.back();  
16:        sta.pop_back();  
17:        result.push_back(node->val);  
18:        node =node->right;  
19:      }  
20:      return result;  
21:    }  



Monday, January 7, 2013

[LeetCode] Symmetric Tree 解题报告


Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
For example, this binary tree is symmetric:
    1
   / \
  2   2
 / \ / \
3  4 4  3
But the following is not:
    1
   / \
  2   2
   \   \
   3    3
Note:
Bonus points if you could solve it both recursively and iteratively.
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem

[解题思路]
非递归解法:按层遍历,每一层检查一下是否对称。

递归解法:

其中左子树和右子树对称的条件:
  1. 两个节点值相等,或者都为空
  2. 左节点的左子树和右节点的右子树对称
  3. 左节点的右子树和右节点的左子树对称



[Code]
非递归解法
1:  bool isSymmetric(TreeNode *root) {  
2:       if(root == NULL) return true;  
3:       vector<TreeNode*> visitQueue;  
4:       visitQueue.push_back(root);  
5:       int curLevel=1;            
6:       while(curLevel >0)  
7:       {  
8:            int i=0;  
9:            while(i<curLevel)  
10:            {  
11:                 TreeNode* p = visitQueue[i];  
12:                 i++;  
13:                 if(p==NULL) continue;  
14:                 visitQueue.push_back(p->left);  
15:                 visitQueue.push_back(p->right);  
16:            }  
17:            int start = 0, end = curLevel-1;  
18:            while(start< end)   
19:            {   
20:                 TreeNode *pl = visitQueue[start];   
21:                 TreeNode *pr = visitQueue[end];   
22:                 int l = pl== NULL? -1:pl->val;   
23:                 int r = pr== NULL? -1: pr->val;   
24:                 if(l!=r)   
25:                      return false;   
26:                 start++;   
27:                 end--;   
28:            }   
29:            visitQueue.erase(visitQueue.begin(), visitQueue.begin() + curLevel);                 
30:            curLevel = visitQueue.size();   
31:       }   
32:       return true;   
33:  }  

递归解法

1:    bool isSymmetric(TreeNode *root) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      if(root == NULL) return true;  
5:      return isSym(root->left, root->right);  
6:    }  
7:    bool isSym(TreeNode *left, TreeNode *right)  
8:    {  
9:      if(left == NULL)  
10:        return right ==NULL;  
11:      if(right == NULL)  
12:        return left == NULL;  
13:      if(left->val != right->val)  
14:        return false;  
15:      if(!isSym(left->left, right->right))  
16:        return false;  
17:      if(!isSym(left->right, right->left))  
18:        return false;  
19:      return true;  
20:    }  






Sunday, December 30, 2012

[LeetCode] Recover Binary Search Tree 解题报告


Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem

[解题报告]
O(n)空间的解法比较直观,中序遍历一遍以后,重新赋值一遍即可,这个解法可以面向n个元素错位的情况。但是对于O(1)空间的解法,最开始的想法是,可以考虑采用类似最大堆的调正过程的算法,但是这样又可能会破坏树的原有结构。暂未想出来解法。

只能给个O(n)空间的解法。

[Code]
1:    void recoverTree(TreeNode *root) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      vector<TreeNode*> list;  
5:      vector<int > vals;  
6:         InOrderTravel(root, list, vals);  
7:            sort(vals.begin(), vals.end());  
8:            for(int i =0; i< list.size(); i++)  
9:            {  
10:                 list[i]->val = vals[i];  
11:            }            
12:    }  
13:       void InOrderTravel(TreeNode* node, vector<TreeNode*>& list, vector<int>& vals)  
14:       {  
15:            if(node == NULL) return;  
16:            InOrderTravel(node->left, list, vals);  
17:            list.push_back(node);  
18:            vals.push_back(node->val);  
19:            InOrderTravel(node->right, list, vals);            
20:       }  

Updates:  3/16/2013
Searched in the web. Actually, there is a smart solution to travel the tree with two node.
The link is http://discuss.leetcode.com/questions/272/recover-binary-search-tree

1:  void Solution::recoverTree(TreeNode *h) {  
2:    TreeNode *f1=NULL, *f2=NULL;  
3:    bool found = false;  
4:    TreeNode *pre, *par = 0; // previous AND parent  
5:    while(h) { // Morris Traversal  
6:      if(h->left == 0) {  
7:        if(par && par->val > h->val) { // inorder previous is: par  
8:          if(!found) {  
9:            f1 = par;  
10:            found = true;  
11:          }  
12:          f2 = h;  
13:        }  
14:        par = h;  
15:        h = h->right;  
16:        continue;  
17:      }  
18:      pre = h->left;  
19:      while(pre->right != 0 && pre->right != h)   
20:        pre = pre->right;  
21:      if(pre->right == 0) {  
22:        pre->right = h;  
23:        h = h->left;  
24:      } else {  
25:        pre->right = 0;  
26:        if(pre->val > h->val) { // inorder previous is: pre  
27:          if(!found) {  
28:            f1 = pre;  
29:            found =true;  
30:          }  
31:          f2 = h;  
32:        }  
33:        par = h;  
34:        h = h->right;  
35:      }  
36:    }  
37:    if(found)  
38:      swap(f1->val, f2->val);  
39:  }  


Update: 3/21/2013  上一个解法不容易看清楚,添加分析。
O(1)的解法就是
Inorder traverse, keep the previous tree node,
Find first misplaced node by
if ( current.val < prev.val )
   Node first = prev;

Find second by
if ( current.val < prev.val )
   Node second = current;

After traversal, swap the values of first and second node. Only need two pointers, prev and current node. O(1) space.

但是这个解法的前提是Traverse Tree without Stack. 中序遍历如何才能不使用栈。这里就要引入一个概念, Threaded Binary Tree。So, we first create links to Inorder successor and print the data using these links, and finally revert the changes to restore original tree.

1. Initialize current as root 
2. While current is not NULL
   If current does not have left child
      a) Print current’s data
      b) Go to the right, i.e., current = current->right
   Else
      a) Make current as right child of the rightmost node in current's left subtree
      b) Go to this left child, i.e., current = current->left


代码如下:

/* Function to traverse binary tree without recursion and without stack */
vector<int> inorderTraversal(TreeNode *root)
{
       vector<int> result;  
       TreeNode  *current,*pre;

       if(root == NULL)
       return result;

       current = root;
       while(current != NULL)
       {                
             if(current->left == NULL)
             {
                    result.push_back(current->val);
                    current = current->right;     
             }   
             else
             {
                    /* Find the inorder predecessor of current */
                    pre = current->left;
                    while(pre->right != NULL && pre->right != current)
                           pre = pre->right;

                    /* Make current as right child of its inorder predecessor */
                    if(pre->right == NULL)
                    {
                           pre->right = current;
                           current = current->left;
                    }
                   
                    /* Revert the changes made in if part to restore the original
                 tree i.e., fix the right child of predecssor */  
                    else
                    {
                           pre->right = NULL;
                           result.push_back(current->val);
                           current = current->right;     
                    } /* End of if condition pre->right == NULL */
             } /* End of if condition current->left == NULL*/
       } /* End of while */

       return result;
}


那么,基于这个双指针遍历,可以把错置节点的判断逻辑加进去,就可以完美的在O(1)空间内,完成树的重构。

[Code]
改动代码如红字所示。增加了一个pointer -- parent来记录上一个访问节点。整个遍历过程中,使用(parent->val > current->val)来寻找违规节点,但是区别是,要获取第一次violation的parent和第二次violation的current,然后交换。

void recoverTree(TreeNode *root)
{     
       TreeNode *f1=NULL, *f2=NULL;
       TreeNode  *current,*pre, *parent=NULL;

       if(root == NULL)
             return;
       bool found = false;
       current = root;
       while(current != NULL)
       {                
             if(current->left == NULL)
             {
                    if(parent && parent->val > current->val)
                    {
                           if(!found)
                           {
                                 f1 = parent;
                                 found = true;
                           }
                           f2 = current;
                    }
                    parent = current;
                    current = current->right;     
             }   
             else
             {
                    /* Find the inorder predecessor of current */
                    pre = current->left;
                    while(pre->right != NULL && pre->right != current)
                           pre = pre->right;

                    /* Make current as right child of its inorder predecessor */
                    if(pre->right == NULL)
                    {
                           pre->right = current;
                           current = current->left;
                    }

                    /* Revert the changes made in if part to restore the original
                    tree i.e., fix the right child of predecssor */  
                    else
                    {
                           pre->right = NULL;
                           if(parent->val > current->val)
                           {
                                 if(!found)
                                 {
                                        f1 = parent;       
                                        found = true;
                                 }
                                 f2 = current;
                           }
                           parent = current;
                           current = current->right;     
                    } /* End of if condition pre->right == NULL */
             } /* End of if condition current->left == NULL*/
       } /* End of while */

       if(f1 && f2)
             swap(f1->val, f2->val);
}