Showing posts with label review. Show all posts
Showing posts with label review. Show all posts

Monday, August 5, 2013

[Microsoft] string permutation with upcase and lowcase

Give a string, which only contains a-z. List all the permutation of upcase and lowcase.
For example, str = "ab",  the output should be
"ab", "aB", "Ab", "AB"
for str = "abc", the output should be
"abc", "abC", "aBc", "aBC", "Abc", "AbC", "ABc", "ABC"

[Thoughts]
首先,肯定可以用递归来做,每一个节点有大小两种可能。代码可以简单的写成:
  1: void ListPermutation(string sample, int depth, string& result)
  2: {
  3:     if(depth == sample.size())
  4:     {
  5:         prinf("%s\r\n", result.c_str());
  6:         return;
  7:     }
  8:     
  9:     // process low-case char
 10:     result.push_back(sample[depth]);
 11:     ListPermutation(sample, depth+1, result);
 12:     result.pop_back();
 13:     
 14:     //process up-case char
 15:     result.push_back(sample[depth]-32);
 16:     ListPermutation(sample, depth+1, result);
 17:     result.pop_back();
 18: }

但是,如果考虑空间复杂度的话,这是个指数级的实现。如果字符串有几千行或者几万行,内存就不得了了。

如果换个思路想想的话,其实这个题有简单的解法。因为,大写和小写只有两种变化,其实就是0和1的变化。简单的说,如果字符串长L,那么遍历区间[0,2^L-1],对于任意i,将其转换为长度为L的二进制表示,然后根据每一位二进制是0还是1,来决定输出大写还是小写。实现如下:
  1: void ListPermutation(string sample)
  2: {
  3:     int L = sample.size();
  4:     long end = pow(2, L) -1;
  5:     for(int i =0; i< end; i++)
  6:     {
  7:         // Convert Dec to Binary, 
  8:         // return a string to represent binary data with size L
  9:         string binaryRep = ConvertDecToBinany(i, L);
 10:         
 11:         string output;
 12:         for(int j=0; j<L; j++)
 13:         {
 14:             if(binaryRep[j] == '0') //low case
 15:             {
 16:                 output.push_back(sample[j]);
 17:             }
 18:             else
 19:             {
 20:                 output.push_back(sample[j]-32);
 21:             }        
 22:         }
 23:         printf("%s\r\n", output.c_str());
 24:     }
 25: }

这样的话,整体思路就更清晰,而且内存使用是O(L)。





Sunday, April 7, 2013

[LeetCode] Merge Intervals, Solution


Given a collection of intervals, merge all overlapping intervals.
For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].
» Solve this problem

[Thoughts]
复用一下Insert Intervals的解法即可,http://fisherlei.blogspot.com/2012/12/leetcode-insert-interval.html
创建一个新的interval集合,然后每次从旧的里面取一个interval出来,然后插入到新的集合中。

[Code]
黄色高亮部分是复用的Code.

1:       vector<Interval> merge(vector<Interval> &intervals) {            
2:            vector<Interval> result;  
3:            for(int i =0; i< intervals.size(); i++)  
4:            {  
5:                 insert(result, intervals[i]);  
6:            }  
7:            return result;  
8:       }  
9:       void insert(vector<Interval> &intervals, Interval newInterval) {        
10:            vector<Interval>::iterator it = intervals.begin();   
11:            while(it!= intervals.end())   
12:            {   
13:                 if(newInterval.end<it->start)   
14:                 {   
15:                      intervals.insert(it, newInterval);   
16:                      return;   
17:                 }   
18:                 else if(newInterval.start > it->end)   
19:                 {   
20:                      it++;   
21:                      continue;   
22:                 }   
23:                 else   
24:                 {   
25:                      newInterval.start = min(newInterval.start, it->start);   
26:                      newInterval.end = max(newInterval.end, it->end);   
27:                      it =intervals.erase(it);             
28:                 }           
29:            }   
30:            intervals.insert(intervals.end(), newInterval);    
31:       }   



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



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

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










Sunday, March 10, 2013

[LeetCode] Longest Valid Parentheses, Solution


Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.
For "(()", the longest valid parentheses substring is "()", which has length = 2.
Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.
» Solve this problem

[Thoughts]
维护一个栈,每次维护上一个可能的左边际。


[Code]
1:       int longestValidParentheses(string s) {  
2:            const char* str = s.c_str();  
3:            int nMax=0;  
4:            const char *p = str;  
5:            vector<const char*> sta;  
6:            while(*p !='\0')  
7:            {  
8:                 if(*p == '(')  
9:                 {  
10:                      sta.push_back(p);                      
11:                 }  
12:                 else  
13:                 {  
14:                      if(!sta.empty() && *sta.back()=='(')  
15:                      {  
16:                           sta.pop_back();  
17:                           nMax = max(nMax, p-(sta.empty()?str-1:sta.back()));  
18:                      }  
19:                      else  
20:                      {  
21:                           sta.push_back(p);  
22:                      }  
23:                 }  
24:                 p++;  
25:            }  
26:            return nMax;  
27:       }  


Monday, March 4, 2013

[LeetCode] Palindrome Partitioning II, Solution

Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.
» Solve this problem

[Thoughts]
凡是求最优解的,一般都是走DP的路线。这一题也不例外。首先求dp函数,

定义函数
D[i,n] = 区间[i,n]之间最小的cut数,n为字符串长度

 a   b   a   b   b   b   a   b   b   a   b   a
                     i                                  n
如果现在求[i,n]之间的最优解?应该是多少?简单看一看,至少有下面一个解


 a   b   a   b   b   b   a   b   b   a   b   a
                     i                   j   j+1     n

此时  D[i,n] = min(D[i, j] + D[j+1,n])  i<=j <n。这是个二维的函数,实际写代码时维护比较麻烦。所以要转换成一维DP。如果每次,从i往右扫描,每找到一个回文就算一次DP的话,就可以转换为
D[i] = 区间[i,n]之间最小的cut数,n为字符串长度, 则,

D[i] = min(1+D[j+1] )    i<=j <n

有个转移函数之后,一个问题出现了,就是如何判断[i,j]是否是回文?每次都从i到j比较一遍?太浪费了,这里也是一个DP问题。
定义函数
P[i][j] = true if [i,j]为回文

那么
P[i][j] = str[i] == str[j] && P[i+1][j-1];

基于以上分析,实现如下:
1:       int minCut(string s) {  
2:            int len = s.size();  
3:            int D[len+1];  
4:            bool P[len][len];  
5:            //the worst case is cutting by each char  
6:            for(int i = 0; i <= len; i++)   
7:            D[i] = len-i;  
8:            for(int i = 0; i < len; i++)  
9:            for(int j = 0; j < len; j++)  
10:            P[i][j] = false;  
11:            for(int i = len-1; i >= 0; i--){  
12:                 for(int j = i; j < len; j++){  
13:                      if(s[i] == s[j] && (j-i<2 || P[i+1][j-1])){  
14:                           P[i][j] = true;  
15:                           D[i] = min(D[i],D[j+1]+1);  
16:                      }  
17:                 }  
18:            }  
19:            return D[0]-1;  
20:       }  


或者可以考虑使用回溯+剪枝,比如:

1:    int minCut(string s) {  
2:      int min = INT_MAX;  
3:      DFS(s, 0, 0, min);  
4:      return min;  
5:    }  
6:    void DFS(string &s, int start, int depth, int& min)  
7:    {     
8:      if(start == s.size())  
9:      {  
10:        if(min> depth-1)  
11:          min = depth-1;  
12:        return;  
13:      }  
14:      for(int i = s.size()-1; i>=start; i--)  //find the biggest palindrome first
15:      {  
16:        if(isPalindrome(s, start, i))  
17:        {        
18:          DFS(s, i+1, depth+1, min);  
19:        }  
20:        if(min!=INT_MAX)  //if get result, then stop search.
21:          break;  
22:      }  
23:    }  
24:    bool isPalindrome(string &s, int start, int end)  
25:    {  
26:      while(start< end)  
27:      {  
28:        if(s[start] != s[end])  
29:          return false;  
30:        start++; end--;  
31:      }  
32:      return true;  
33:    }  

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


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



[LeetCode] Best Time to Buy and Sell Stock III Solution


Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
» Solve this problem

[Thoughts]
One dimensional dynamic planning.
Given an i, split the whole array into two parts:
[0,i] and [i+1, n], it generates two max value based on i, Max(0,i) and Max(i+1,n)
So, we can define the transformation function as:
Maxprofix = max(Max(0,i) + Max(i+1, n))  0<=i<n
Pre-processing Max(0,i) might be easy, but I didn't figure an efficient way to generate Max(i+1,n) in one pass.

[Code]
1:    int maxProfit(vector<int> &prices) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      int index =0;  
5:      int max1, max2;  
6:      int max =0;  
7:      for(int i =0; i< prices.size(); i++)  
8:      {  
9:        max1=SearchMax(prices,0,i);  
10:        max2 = SearchMax(prices,i+1, prices.size()-1);  
11:        if(max < max1+max2)  
12:          max = max1+max2;  
13:      }  
14:      return max;  
15:    }  
16:    int SearchMax(vector<int>& prices, int start, int end)  
17:    {  
18:      int max=0;  
19:      int min=INT_MAX;  
20:      for(int i =start; i<= end; i++)  
21:      {  
22:        if(min> prices[i]) min = prices[i];  
23:        int diff = prices[i] -min;  
24:        if(diff> max)  
25:        {  
26:          max = diff;          
27:        }  
28:      }  
29:      return max;  
30:    }  

Update 03/12/2014
Just see the comments. Looks I didn't post the right code.
Line 6~12 and Line 15~21 can be merged into one pass. But keep it for readability.

1:  int maxProfit(vector<int> &prices) {   
2:       if(prices.size() <= 1) return 0;  
3:       vector<int> maxFromLeft(prices.size(), 0);  
4:       vector<int> maxFromRight(prices.size(), 0);  
5:       int minV = INT_MAX, maxP = INT_MIN;  
6:       for(int i =0; i< prices.size(); i++)  
7:       {  
8:            if(minV > prices[i]) minV = prices[i];  
9:            int temp = prices[i] - minV;  
10:            if(temp > maxP) maxP = temp;  
11:            maxFromLeft[i] = maxP;  
12:       }  
13:       int maxV = INT_MIN;  
14:       maxP = INT_MIN;  
15:       for(int i =prices.size()-1; i>=0; i--)  
16:       {  
17:            if(maxV < prices[i]) maxV = prices[i];  
18:            int temp = maxV - prices[i];  
19:            if(temp > maxP) maxP = temp;  
20:            maxFromRight[i] = maxP;  
21:       }  
22:       int maxProfit = INT_MIN;  
23:       for(int i =0; i< prices.size()-1; i++)  
24:       {  
25:            int sum = maxFromLeft[i] + maxFromRight[i+1];  
26:            if(sum > maxProfit) maxProfit = sum;  
27:       }  
28:       if(maxProfit < maxFromRight[0])  
29:            maxProfit = maxFromRight[0];  
30:       return maxProfit;   
31:  }   






Saturday, January 12, 2013

[LeetCode] Wildcard Matching, Solution


Implement wildcard pattern matching with support for '?' and '*'.
'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false
» Solve this problem

[解题思路]
主要是*的匹配问题。p每遇到一个*,就保留住当前*的坐标和s的坐标,然后s从前往后扫描,如果不成功,则s++,重新扫描。

[Code]
1:    bool isMatch(const char *s, const char *p) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      bool star = false;  
5:      const char *str, *ptr;  
6:      for(str = s, ptr =p; *str!='\0'; str++, ptr++)  
7:      {  
8:        switch(*ptr)  
9:        {  
10:          case '?':  
11:            break;  
12:          case '*':  
13:            star =true;  
14:            s=str, p =ptr;  
15:            while(*p=='*')  
16:              p++;  
17:            if(*p == '\0') // 如果'*'之后,pat是空的,直接返回true  
18:              return true;  
19:            str = s-1;  
20:            ptr = p-1;  
21:            break;  
22:          default:  
23:          {  
24:            if(*str != *ptr)  
25:            {  
26:              // 如果前面没有'*',则匹配不成功  
27:              if(!star)  
28:                return false;  
29:              s++;  
30:              str = s-1;  
31:              ptr = p-1;  
32:            }  
33:          }  
34:        }  
35:      }  
36:      while(*ptr== '*')  
37:        ptr++;  
38:      return (*ptr == '\0');  
39:    }  


[LeetCode] Validate Binary Search Tree 解题报告


Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
  • The left subtree of a node contains only nodes with keys less than the node's key.
  • The right subtree of a node contains only nodes with keys greater than the node's key.
  • Both the left and right subtrees must also be binary search trees.
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem

[解题思路]

对于每一个子树,限制它的最大,最小值,如果超过则返回false。
对于根节点,最大最小都不限制;
每一层节点,左子树限制最大值小于根,右子树最小值大于根;
但是比较有趣的是,在递归的过程中还得不断带入祖父节点的值。

或者,中序遍历该树,然后扫描一遍看是否递增。


[Code]
递归
红字部分是关键点。不把变量遗传下去的话,没法解决如下例子:
{10,5,15,#,#,6,20}


1:    bool isValidBST(TreeNode *root) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      return VerifyBST(root, false, false, 0,0);  
5:    }  
6:    bool VerifyBST(TreeNode* root, bool left, bool right, int lmax, int rmin)  
7:    {  
8:      if(root== NULL)  
9:        return true;  
10:      if(left && root->val >= lmax) return false;  
11:      if(right && root->val <=rmin) return false;  
12:      bool leftValid = VerifyBST(root->left, true, right, root->val, rmin);  
13:      bool rightValid = VerifyBST(root->right, left, true, lmax, root->val);  
14:      return leftValid&&rightValid;        
15:    }  


Updates:
换个看起来简洁的

1:       bool isValidBST(TreeNode *root) {  
2:            return IsValidBST(root, INT_MIN, INT_MAX);  
3:       }  
4:       bool IsValidBST(TreeNode* node, int MIN, int MAX)   
5:       {  
6:            if(node == NULL)  
7:                  return true;  
8:            if(node->val > MIN   
9:                      && node->val < MAX  
10:                      && IsValidBST(node->left,MIN,node->val)  
11:                      && IsValidBST(node->right,node->val,MAX))  
12:                 return true;  
13:            else   
14:                 return false;  
15:       }  

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