高效面试之二叉树

来源:互联网 发布:如何修改淘宝账号名称 编辑:程序博客网 时间:2024/05/12 03:37
题目四大类:
1.二叉树的遍历
先/中/后/层次/morris
2.二叉树的构建
3.二叉树的递归
4.二叉搜索树

二叉树基本操作题目编号:
1.二叉树的创建,遍历(4种)
2.知道其中两种遍历方式,二叉树重构。
3.二叉树搜索树的创建,查找,插入,删除操作

leetcode编号:
遍历
1.判断两个树是否相同
2.判断两个树是否对称
3.判断是否为平衡二叉树
4.转换二叉树为单链表
5.z字形遍历
二叉查找树
1.给定数字n,求能够构建的二叉查找树的个数
2.给定一个二叉树,判断是否为二叉查找树
3.转换有序数组为二叉查找树
4.转换有序链表为二叉查找树
二叉树递归
1.求最大高度
2.求最小高度
3.给定一个值,看找到一条从root到leaf的路径上的节点和为给定值
4.最二叉树最大路径和,(起始点和结束点随意,dp)
5.从root到leaf的值构成一个数,求和


一.二叉树的定义 

 struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  };

概念

二叉树:根,左子树,右子数组成。

满二叉树:每一层都是满的。

完全二叉树:前i-1都是满的,最后一层可以不满,左叶子节点不存在,右叶子节点必不存在

性质

性质1:第i层节点数目最多为:2^(i-1),深度为k的二叉树,节点数最多为2^i-1

性质2:具有n个节点的完全二叉树,深度为[log2(n)]+1 .取整减1 。最简单例子记:3个节点的完全二叉树度为2

性质3:叶子节点比度为2的节点多1

性质4:对一个n个节点的完全二叉树从上到下,从左到右进行编号。则

i=1为根,左为2i,右为2i+1


二、二叉树的遍历

遍历

前、中、后是指的根的位置,左总是比右先遍历。

前:ABDECFGH

中:DBEAGHFC

后:DEBHGFCA

递归遍历

算法实现:

void preorder(BTree* bt)

{

    if(bt!=NULL)

    {

        printf("%d",bt->data);

        preorder(bt->left);

        preorder(bt->right);

    }

}

void inorder(BTree* bt)

{

    if(bt!=NULL)

    {

        preorder(bt->left);

        printf("%d",bt->data);

        preorder(bt->right);

    }

}

void postrder(BTree* bt)

{

    if(bt!=NULL)

    {

        preorder(bt->left);

        preorder(bt->right);

        printf("%d",bt->data);

    }

}

非递归:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode *root) {
        std:stack<TreeNode *> s;
        vector<int> result;
        TreeNode *p=root;
        while( p!=NULL || !s.empty() )
        {
           
            while(p!=NULL)
            {
                result.push_back(p->val);
                s.push(p);
                p=p->left;
            }
            if(!s.empty())
            {
                p=s.top();
                s.pop();
                p=p->right;
            }
        }
        return result;

    }
};

void BFS(BTNode* pRoot)

{

    if(pRoot ==NULL)

        return;

    std::deque<BTNode*> treeDeque;

    treeDeque.push_back(pRoot);

 

    while(!treeDeque.empty())

    {

        BTNode* pNode =treeDeque.front();

        printf("%d\t", pNode->value);

        

        if(pNode->pLeft!= NULL)

        {

            treeDeque.push_back(pNode->pLeft);

        }

 

        if(pNode->pRight!= NULL)

        {

            treeDeque.push_back(pNode->pRight);

        }

    }

}


二叉树创建
BTNode *create() 
       BTNode *root; 
       char ch; 
       scanf("%c",&ch); 
       if(ch=='#'
         root=NULL; 
       else
       
           root=(BTNode *)malloc(sizeof(BTNode)); 
           root->data=ch; 
           root->lchild=create(); 
           root->rchild=create(); 
       
       return root; 
//先序输入建立二叉树  



三种遍历序列,已知两种,求第三种,我们下面分类讨论一下:

1)已知先序和中序,求后序

我们来举个简单的例子,先序序列为:ABDECF,中序序列为:DBEAFC。

算法思想:先序遍历树的规则为中左右,可以看到先序遍历序列的第一个元素必为树的根节点,比如上例中的A就为根节点。再看中序遍历为:左中右,再根据根节点A,可知左子树包含元素为:DBE,右子树包含元素:FC。然后递归的 进行左子树的求解(左子树的先序为:BDE,中序为:DBE),递归的进行右子树的求解(即右子树的先序为:CF,中序为:FC)。如此递归到没有左右子树为止

  1. class Solution {  
  2. public:  
  3.     /*Recursive*/  
  4.     TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {  
  5.         if(preorder.size() == 0 || preorder.size() != inorder.size()) return NULL;  
  6.         return build(preorder, 0, preorder.size()-1, inorder, 0, inorder.size() - 1);  
  7.     }  
  8.     TreeNode *build(vector<int> &preorder, int start1, int end1, vector<int> &inorder,   
  9.                        int start2, int end2){  
  10.         if(start1 > end1 || start2 > end2) return NULL;  
  11.         int val = preorder[start1];  
  12.         TreeNode* newNode = new TreeNode(val);  
  13.         int k = start2;  
  14.         for(; k <= end2; k++) if(inorder[k] == val) break;  
  15.         newNode->left =  build(preorder, start1 + 1, start1 + k - start2, inorder,   
  16.                      start2, k - 1);  
  17.         newNode->right = build(preorder, start1 + k - start2 + 1, end1, inorder,  
  18.                      k + 1, end2);  
  19.         return newNode;  
  20.     }  
  21. };  

2)已知先序和后序,求中序

同样举上面的例子,先序序列为:ABDECF,后序序列为:DEBFCA。

此种情况是不可唯一确定解的,只能确定根节点,而对于左右子树的组成不确定。

3)已知中序和后序,求先序

同样举上面的例子,中序序列为:DBEAFC,后序序列为:DEBFCA。

算法思想:同样采用分段递归的思想解决。由后序序列知道最后一个节点一定是根节点,此处为A,在根据中序序列知道左子树和右子树,之后在分段递归。



三.二叉查找树
1.定义

左孩子比父节点小,右孩子比父节点大,还有一个特性就是”中序遍历“可以让结点有序

2.基本操作

1)查询(复杂度都是O(h))

指定值,最大值,最小值,前驱和后继,范围查找

递归或者迭代都可以,迭代效率更高

2)插入

插入的节点应该是作为叶子节点。那么,只需要从root开始,往下找到插入的节点的父节点是谁,然后其值小于于父节点的值则作为左叶子节点插入,否则则为右叶子节点

3)删除

<1>单孩子的情况

     这个比较简单,如果删除的节点有左孩子那就把左孩子顶上去,如果有右孩子就把右孩子顶上去。直接把单孩子顶上去

<2>左右都有孩子的情况。

     首先可以这么想象,如果我们要删除一个数组的元素,那么我们在删除后会将其后面的一个元素顶到被删除的位置,

       那么二叉树操作同样也是一样,我们根据”中序遍历“找到要删除结点的后一个结点(找到删除点后继),然后顶上去就行了,原理跟"数组”一样一样的。

    - 查找

  二叉查找树的查找操作可以在O(h)时间内完成,其中h为树的高度。查找的算法很简单,根据二叉查找树的性质,我们先将要比较的元素跟根元素相比较,如果相等则返回,如果大于根结点的key,则继续在右子树中查找,如果小于根结点的key值,则在左子树中查找。这也跟插入过程类似,童鞋们可以想象一下,我就不画图了,画图很麻烦。

  下面的代码完成了在树根为x的树中查找关键字为k的元素,如果存在的话就返回其饮用,不存在,则返回null。

  递归查找的代码为:

复制代码
 1 /** 2      * 查找以x为根结点的树中key的值为k的结点,返回找到的结点或者null 3      * @author Alfred 4      * @param x 根结点 5      * @param k 要查找的整数 6      * @return 找到的结点或者null 7      */ 8     private TreeNode treeSearch(TreeNode x, int k){ 9         if(x == null || k == x.getKey()){10             return x;11         }12         if(k < x.getKey()){13             return treeSearch(x.getLeft(), k);//查左子树14         }else{15             return treeSearch(x.getRight(), k);//查右子树16         }17     }
复制代码

非递归查找的代码为:

 

复制代码
 1 /** 2      * 非递归地查找以x为根结点的树中key的值为k的结点,返回找到的结点或者null 3      * @author Alfred 4      * @param x 根结点 5      * @param k 要查找的整数 6      * @return 找到的结点或者null 7      */ 8     private TreeNode treeSearchNonrecursive(TreeNode x, int k){ 9         while(x != null && k != x.getKey()){10             if(k < x.getKey()){11                 x = x.getLeft();12             }else{13                 x = x.getRight();14             }15         }16         return x;17     }
复制代码
    - 最大值

  根据二叉查找树的性质,树中的最大值一定是位于整棵树的最“右”边的右孩子,因为,二叉查找树的性质中说明了,右子树中的结点都大于或者等于父结点和左子树。所以求最大值是一个很简单的操作。代码如下:

复制代码
 1 /** 2      * 找以x为根结点的二叉查找树中的最大值 3      * @author Alfred 4      * @param x 根结点 5      * @return 最大值结点或者null 6      */ 7     public TreeNode treeMax(TreeNode x){ 8         while(x.getRight() != null){ 9             x = x.getRight();10         }11         return x;12     }
复制代码
    - 最小值

  同理,根据二叉查找树的性质,最小值一定是位于整棵树中最“左”边的左孩子,因为,二叉查找树的性质的性质中说明了,左子树中的结点都小于或者等于父结点和右子树。所以跟求最大值对偶的代码如下:

复制代码
 1 /** 2      * 找以x为根结点的二叉查找树中的最小值 3      * @author Alfred 4      * @param x 根结点 5      * @return 最小值结点或者null 6      */ 7     public TreeNode treeMin(TreeNode x){ 8         while(x.getLeft() != null){ 9             x = x.getLeft();10         }11         return x;12     }
复制代码
    - 后继

  由于在之前的博客里面数结点的定义形式,在处理的时候将树中相同的结点全都合并了起来,因此,位于树中不同位置的结点的key值肯定是不同的。因此,我们将求某一个结点后继结点的操作看成是求大于该结点key值的结点中key值最小的那个结点(有点绕。。。)。

  我们记结点x为输入结点,y为输出结点,即y结点是x结点的后继,在我们这里分两种情况进行讨论:

  1. x结点的右子树不为空。

    根据二叉查找树的性质,y肯定是位于x的右子树上,而且是x的右子树的最小值。

  2. x结点的右子树为空。

    如果存在后继y,则y是x的最低祖先结点,且y的左儿子也是x的祖先。晕了?说的简单些。如果x结点的右子树为空,则以x结点为最“右”孩子的子树t中,x结点一定是这个子树的最大值,根据二叉查找树的性质,只有当存在某一结点y,y的左子树恰好是t的时候,y才是x的后继。现在回去读一读这段开始的话,是不是容易理解多了。

  好了,了解了基本的算法,就让我贴上代码吧~

复制代码
 1     /** 2      * 找结点x的后继结点 3      * @author Alfred 4      * @param x 结点 5      * @return x的后继结点或者null 6      */ 7     public TreeNode treeSuccessor(TreeNode x){ 8         //第一种情况 9         if(x.getRight() != null){10             return treeMin(x.getRight());11         }12         //第二种情况13         TreeNode tmpNode = x.getParent();14         while(tmpNode != null && x == tmpNode.getRight()){15             x = tmpNode;16             tmpNode = tmpNode.getParent();17         }18         return tmpNode;19     }
复制代码

 

 这个算法就是按照上面提到的两种情况来实现的,时间复杂度为O(h),h为树的高度。

    - 前驱

  求结点的前驱的算法与后继的算法是对称的。其时间复杂度也是O(h)。在处理上也分为两种情况,我就直接上代码了,有心的童鞋们自己想一下吧~

复制代码
 1 /** 2      * 找结点x的前趋结点 3      * @author Alfred 4      * @param x 结点 5      * @return x的前趋结点或者null 6      */ 7     public TreeNode treePredecessor(TreeNode x){ 8         //第一种情况 9         if(x.getLeft() != null){10             return treeMax(x.getLeft());11         }12         //第二种情况13         TreeNode tmpNode = x.getParent();14         while(tmpNode != null && x == tmpNode.getLeft()){15             x = tmpNode;16             tmpNode = tmpNode.getParent();17         }18         return tmpNode;19     }



上面的代码 关键是找后继



四.二叉树题目汇总

1、编号87 Scramble String

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great":
    great
   /    \
  gr    eat
 / \    /  \
g   r  e   at
           / \
          a   t
To scramble the string, we may choose any non-leaf node and swap its two children.
For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".
    rgeat
   /    \
  rg    eat
 / \    /  \
r   g  e   at
           / \
          a   t
We say that "rgeat" is a scrambled string of "great".
Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".
    rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a
We say that "rgtae" is a scrambled string of "great".
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

很奇怪的一道题,题目要看半天。难度不大,但是因为是树类题目的第一次出现,需要特别注意。方法是递归。观察到要是两个串相等,则必须满足:1含有相同的字母;2当把两个串分别拆成两部分后,第一串的两部分分别跟后一串的两部分相比,只要比得上一次就相等。了解规律之后,容易编写程序如下:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /*Recursive*/  
  2. bool isScramble(string s1, string s2) {  
  3.     if (s1 == s2) return true/*Improve performance*/  
  4.       
  5.     int A[26] = {0};  
  6.     for(int i = 0; i < s1.length(); i++) {  
  7.         A[s1[i]-'a']++;  
  8.         A[s2[i]-'a']--;  
  9.     }  
  10.     for (int i = 0; i < 26; i++)   
  11.         if (A[i] != 0) return false;  
  12.       
  13.     for (int i = 1; i < s1.length (); ++i) {  
  14.         if (isScramble(s1.substr(0, i), s2.substr(0, i)) &&  
  15.             isScramble(s1.substr(i), s2.substr(i)))/*i to the end of the string*/  
  16.             return true;  
  17.           
  18.         if (isScramble(s1.substr(0, i), s2.substr(s1.length() - i)) &&  
  19.             isScramble(s1.substr(i), s2.substr(0, s1.length() - i)))  
  20.             return true;  
  21.     }  
  22.       
  23.     return false;  
  24. }  


2、编号95 Unique Binary Search Trees

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

DP解。关于DP理论点这里。

使用两层循环。i表示当前树的总结点数。j表示树其中一个分支的结点数。则总的数量等于这个分支的数量加上另外一个分支(结点数i-1-j)的数量。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int numTrees(int n) {  
  2.     if(n == 1) return 1;  
  3.   
  4.     vector<int> dp;  
  5.     for(int i = 0; i < n+1; i++) dp.push_back(0); /*safeguard at 0*/  
  6.     dp[0] = 1;  
  7.     dp[1] = 1;  
  8.        
  9.     for(int i = 2; i < n+1; i++)  
  10.        for(int j = 0; j < i; j++)  
  11.            dp[i] += (dp[j]*dp[i-1-j]);  
  12.       
  13.     return dp[n];  
  14. }  


3、编号96 Unique Binary Search Trees II

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

上题的升级版,使用了树的链接表作为数据结构,并且要求得到所有的子树。使用递归法解。绝大部分树类问题都可以用递归解。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1.  /*Recursive*/  
  2. class Solution {  
  3. public:  
  4.     vector<TreeNode *> generateTrees(int n) {  
  5.         if(n == 0) return generate(1, 0);  
  6.         return generate(1, n);  
  7.     }  
  8.       
  9.     vector<TreeNode*> generate(int start, int end){  
  10.         vector<TreeNode*> subTree;  
  11.         if(start > end){  
  12.             subTree.push_back(NULL);  
  13.             return subTree;  
  14.         }  
  15.         /*Create tree procedure: Create left and right, then new the mid node, then push mid node*/  
  16.         for(int i = start; i <= end; i++){<span style="font-family: Arial, Helvetica, sans-serif;">/*This two loop garantees the Unique Binary Tree*/  
  17. </span>            vector<TreeNode*> leftSubs = generate(start, i-1);  
  18.             vector<TreeNode*> rightSubs = generate(i+1, end);  
  19.             for(int j = 0; j < leftSubs.size(); j++){  
  20.                 for(int k = 0; k < rightSubs.size(); k++){  
  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.     }  
  30. };  

4、编号97 Binary Tree Inorder Traversal

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?

中序遍历是先处理左边,然后中间,最后后边。递归很简单,但题目额外要求用非递归方法,则必须使用额外的栈来做。先列出递归解法如下。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     /*Recursive Solution*/  
  4.     vector<int> inorderTraversal(TreeNode *root) {  
  5.         vector<int> result;  
  6.         Traverse(result, root);  
  7.         return result;  
  8.     }  
  9.       
  10.     void Traverse(vector<int> &result, TreeNode* root){  
  11.         if(root == NULL) return;  
  12.         Traverse(result, root->left);  
  13.         result.push_back(root->val);  
  14.         Traverse(result, root->right);  
  15.     }  
  16. };  
非递归解法如下:
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     /*Iterative*/  
  4.     vector<int> inorderTraversal(TreeNode *root) {  
  5.         vector<int> result;  
  6.         if(root == NULL) return result;  
  7.           
  8.         vector<TreeNode*> stack;  
  9.   
  10.         TreeNode *node = root;  
  11.           
  12.         while(stack.size() != 0 || node != NULL){  
  13.             while(node != NULL){  
  14.                 stack.push_back(node);  
  15.                 node = node->left;  
  16.             }  
  17.             node = stack.back();  
  18.             stack.pop_back();  
  19.             result.push_back(node->val);  
  20.             node = node->right;  
  21.         }  
  22.       
  23.         return result;  
  24.     }  
  25. };  

5、编号99 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.

注意,空树被判定为合理的BST树。并且,当存在相同值的时候,BST不满足。然后写一个递归方法判定大小就可以了。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     bool isValidBST(TreeNode *root) {  
  4.         if(root == NULL) return true;   
  5.         return Recursive(root, -INT_MAX, INT_MAX);  
  6.     }  
  7.       
  8.     bool Recursive(TreeNode *root, int min, int max){  
  9.         if(root->val <= min || root->val >= max) return false;  
  10.           
  11.         if(root->left != NULL){  
  12.             if(root->left->val >= root->val) return false;  
  13.             if(!Recursive(root->left, min, root->val)) return false;  
  14.         }  
  15.           
  16.         if(root->right != NULL){  
  17.             if(root->right->val <= root->val) return false;  
  18.             if(!Recursive(root->right, root->val, max)) return false;  
  19.         }  
  20.           
  21.         return true;  
  22.     }  
  23. };  

6、编号100 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?

如果没有空间要求的话,建立一个数组就可以直接解。因为二叉查找树的中序遍历既可以得到一个排好序的数组,可以很容易观察出错误的元素。但是若不用额外空间(递归也不能用),就只能通过复杂的指针操作来做。下面是网上找到的解答,比较长,但有详细注释。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1.  /*O(1) Space solution*/  
  2.  /* Function to traverse binary tree without recursion and without stack */  
  3. class Solution {  
  4. public:  
  5.     void recoverTree(TreeNode *root) {  
  6.        TreeNode *f1 = NULL, *f2 = NULL;  
  7.        TreeNode *current, *pre;  
  8.          
  9.        TreeNode *parent = NULL;   
  10.        bool found = false;  
  11.   
  12.        if(root == NULL) return;  
  13.          
  14.        current = root;  
  15.        while(current != NULL){                  
  16.              if(current->left == NULL){  
  17.                     if(parent && parent->val > current->val){  
  18.                            if(!found) {  
  19.                                  f1 = parent;  
  20.                                  found = true;  
  21.                            }  
  22.                            f2 = current;  
  23.                     }  
  24.                     parent = current;  
  25.                     current = current->right;       
  26.              }     
  27.              else {  
  28.                     /* Find the inorder predecessor of current */  
  29.                     pre = current->left;  
  30.                     while(pre->right != NULL && pre->right != current)  
  31.                            pre = pre->right;  
  32.   
  33.                     /* Make current as right child of its inorder predecessor */  
  34.                     if(pre->right == NULL){  
  35.                            pre->right = current;  
  36.                            current = current->left;  
  37.                     }  
  38.   
  39.                     /* Revert the changes made in if part to restore the original 
  40.                     tree i.e., fix the right child of predecssor */    
  41.                     else {  
  42.                            pre->right = NULL;  
  43.                            if(parent->val > current->val) {  
  44.                                  if(!found) {  
  45.                                         f1 = parent;        
  46.                                         found = true;  
  47.                                  }  
  48.                                  f2 = current;  
  49.                            }  
  50.                            parent = current;  
  51.                            current = current->right;       
  52.                     } /* End of if condition pre->right == NULL */  
  53.              } /* End of if condition current->left == NULL*/  
  54.        } /* End of while */  
  55.   
  56.        if(f1 && f2) swap(f1->val, f2->val);  
  57.     }  
  58. };  

7、编号101 Same Tree

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.

比较简单。注意不仅仅要比较树的结构,结点的值也要处理。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     bool isSameTree(TreeNode *p, TreeNode *q) {  
  4.         return Traverse(p, q);  
  5.     }  
  6.       
  7.     bool Traverse(TreeNode *p, TreeNode *q){  
  8.         if(p == NULL) { if(q != NULL) return false; }  
  9.         if(q == NULL) { if(p != NULL) return false; }  
  10.           
  11.         if(p == NULL && q == NULL) return true;  
  12.           
  13.         if(p->val != q->val) return false;  
  14.           
  15.         if(p->left == NULL) { if(q->left != NULL) return false; }  
  16.         if(p->right == NULL) { if(q->right != NULL) return false; }  
  17.           
  18.         if(!Traverse(p->left, q->left)) return false;  
  19.         if(!Traverse(p->right, q->right)) return false;  
  20.           
  21.         return true;  
  22.     }  
  23. };  

8、编号102 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

使用递归(又是!)。注意22和23行的对称比较。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     /*Recursive solution, need iterative*/  
  4.     bool isSymmetric(TreeNode *root) {    
  5.       if(root == NULL) return true;    
  6.       return isSym(root->left, root->right);    
  7.     }   
  8.       
  9.     bool isSym(TreeNode *left, TreeNode *right) {    
  10.       if(left == NULL) return right == NULL;    
  11.       if(right == NULL) return left == NULL;    
  12.       if(left->val != right->val) return false;    
  13.       if(!isSym(left->left, right->right)) return false;  
  14.       if(!isSym(left->right, right->left)) return false;   
  15.         
  16.       return true;    
  17.     }  
  18.   
  19. };  

9、编号103 Binary Tree Level Order Traversal

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]
]

树的广度优先遍历。使用队列实现。由于输出的关系,这里使用了两个队列,一个用来记录结点,一个记录结点的层级。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     vector<vector<int> > levelOrder(TreeNode *root) {  
  4.         vector<vector<int>> result;  
  5.         if(root == NULL) return result;  
  6.           
  7.         queue<TreeNode*> q;  
  8.         queue<int> queue_level;  
  9.         q.push(root);   
  10.         queue_level.push(0);  
  11.           
  12.         vector<int> elem;  
  13.         result.push_back(elem);  
  14.           
  15.         while(q.size() > 0){  
  16.             TreeNode* x = q.front();  
  17.             q.pop();  
  18.             int l = queue_level.front();  
  19.             queue_level.pop();  
  20.               
  21.             if(l > (result.size()-1) ){  
  22.                 vector<int> elem;  
  23.                 result.push_back(elem);  
  24.             }  
  25.             result[l].push_back(x->val);  
  26.               
  27.             if(x->left != NULL){  
  28.                 q.push(x->left);  
  29.                 queue_level.push(l+1);  
  30.             }  
  31.               
  32.             if(x->right != NULL){  
  33.                 q.push(x->right);  
  34.                 queue_level.push(l+1);  
  35.             }  
  36.               
  37.         }  
  38.           
  39.         return result;  
  40.     }  
  41. };  

10、编号104 Binary Tree Zigzag Level Order

Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).
For example:
Given binary tree {3,9,20,#,#,15,7},
    3
   / \
  9  20
    /  \
   15   7
return its zigzag level order traversal as:
[
  [3],
  [20,9],
  [15,7]
]

跟上面那题差不多。区别是要z型输出。定义了新数组tmpArray,当要相反输出的时候就把它倒着放进结果里。在上面题的基础上写的,所以比较长。标记了/*Zigzag*/的是新加入的部分。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     vector<vector<int> > zigzagLevelOrder(TreeNode *root) {  
  4.         vector<vector<int>> result;  
  5.         if(root == NULL) return result;  
  6.           
  7.         queue<TreeNode*> q;  
  8.         queue<int> queue_level;  
  9.           
  10.         vector<int> elem;  
  11.         result.push_back(elem);  
  12.           
  13.         bool leftToRight = false/*Zigzag*/  
  14.         vector<TreeNode*> tmpArray;/*Zigzag*/  
  15.         vector<int> tmpArray_level;  
  16.         tmpArray.push_back(root);  
  17.         tmpArray_level.push_back(0);  
  18.           
  19.         while(tmpArray.size() > 0 || q.size() > 0){  
  20.               
  21.             /*Zigzag~*/  
  22.             if(q.size() == 0){  
  23.                 /*!!!!Flip in each step!!!!!!!*/  
  24.                 for(int i = tmpArray.size()-1; i >= 0 ; i--){  
  25.                     q.push(tmpArray[i]);  
  26.                     queue_level.push(tmpArray_level[i]);  
  27.                 }  
  28.                 leftToRight = !leftToRight;  
  29.                 while(tmpArray.size() > 0) {  
  30.                     tmpArray.pop_back();  
  31.                     tmpArray_level.pop_back();  
  32.                 }  
  33.             }  
  34.             /*~Zigzag*/  
  35.               
  36.             TreeNode *x = q.front();  
  37.             q.pop();  
  38.             int l = queue_level.front();  
  39.             queue_level.pop();  
  40.               
  41.             if(l > (result.size() - 1)){  
  42.                 vector<int> elem;  
  43.                 result.push_back(elem);  
  44.             }  
  45.             result[l].push_back(x->val);  
  46.               
  47.             /*!!!!Flip in each two steps!!!!!!!*/  
  48.             if(leftToRight){  
  49.                 if(x->left != NULL){  
  50.                     tmpArray.push_back(x->left);  
  51.                     tmpArray_level.push_back(l+1);  
  52.                 }  
  53.                   
  54.                 if(x->right != NULL){  
  55.                     tmpArray.push_back(x->right);  
  56.                     tmpArray_level.push_back(l+1);  
  57.                 }  
  58.             }else{  
  59.                 if(x->right != NULL){  
  60.                     tmpArray.push_back(x->right);  
  61.                     tmpArray_level.push_back(l+1);  
  62.                 }  
  63.                   
  64.                 if(x->left != NULL){  
  65.                     tmpArray.push_back(x->left);  
  66.                     tmpArray_level.push_back(l+1);  
  67.                 }  
  68.             }  
  69.         }  
  70.           
  71.         return result;  
  72.     }  
  73. };  

11、编号105 Maximum Depth of Binary Tree

Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
找到树的最大深度。比较简单,但代表了一类题的解法。就是在递归的函数参数里增加变量,一层一层传递下去,以后还会用到。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     int maxDepth(TreeNode *root) {  
  4.         int maxDepth = 0;  
  5.         if(root == NULL) return maxDepth;  
  6.         Recursive(root, 1, maxDepth);  
  7.         return maxDepth;  
  8.     }  
  9.       
  10.     void Recursive(TreeNode* root, int level, int& maxDepth){  
  11.         if(level > maxDepth) maxDepth = level;  
  12.         if(root->left != NULL) Recursive(root->left, level+1, maxDepth);  
  13.         if(root->right != NULL) Recursive(root->right, level+1, maxDepth);  
  14.     }  
  15. };  

12、编号106 Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.
Note: You may assume that duplicates do not exist in the tree.

先通过一个简单的例子找规律。

   1
 /   \
2     3
 \    /
  4  5

preorder是:1,2,4,3,5 

inorder是:2,4,1,5,3 

首先preorder的第一个必然是根(1),然后此节点在inorder中的下标是2,那么在inorder中,处于1之前的两个节点2,4是左子树的;反之5,3是右子树的。 针对左子树,2,4就是它的inorder,而在preorder中,除开第一个根,数两个节点的子序列正好是2,4,这是左子树的preorder。这样这个问题就自然变成递归了: 即,其左子树的preorder是(2,4),inorder是(2,4);类似有右子树preorder(3,5),inorder(5,3)

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     /*Recursive*/  
  4.     TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {  
  5.         if(preorder.size() == 0 || preorder.size() != inorder.size()) return NULL;  
  6.         return build(preorder, 0, preorder.size()-1, inorder, 0, inorder.size() - 1);  
  7.     }  
  8.     TreeNode *build(vector<int> &preorder, int start1, int end1, vector<int> &inorder,   
  9.                        int start2, int end2){  
  10.         if(start1 > end1 || start2 > end2) return NULL;  
  11.         int val = preorder[start1];  
  12.         TreeNode* newNode = new TreeNode(val);  
  13.         int k = start2;  
  14.         for(; k <= end2; k++) if(inorder[k] == val) break;  
  15.         newNode->left =  build(preorder, start1 + 1, start1 + k - start2, inorder,   
  16.                      start2, k - 1);  
  17.         newNode->right = build(preorder, start1 + k - start2 + 1, end1, inorder,  
  18.                      k + 1, end2);  
  19.         return newNode;  
  20.     }  
  21. };  


13、编号107 Construct Binary Tree from Inorder and Postorder Traversal

Given inorder and postorder traversal of a tree, construct the binary tree.
Note: You may assume that duplicates do not exist in the tree.

上一题的类似过程。在postorder中,最后那一个肯定是整棵树的根,然后在inorder中查找这个根, 找到之后就能确定左子树和右子树的后序遍历和中序遍历,然后递归求解。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     TreeNode *buildTree(vector<int> inorder, vector<int> postorder) {  
  4.         if(inorder.size() == 0 || inorder.size() != postorder.size()) return NULL;  
  5.         return build(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);  
  6.     }  
  7.     TreeNode *build(vector<int> &inorder, int start1, int end1, vector<int> &postorder,   
  8.                       int start2, int end2){  
  9.         if(start1 > end1 || start2 > end2) return NULL;  
  10.         int val = postorder[end2];  
  11.         TreeNode* newNode = new TreeNode(val);  
  12.         int k = start1;  
  13.         for(; k <= end1; k++) if(val == inorder[k]) break;  
  14.         newNode->right = build(inorder, k + 1,  end1,  postorder,   
  15.                     end2 - end1 + k, end2 - 1);  
  16.         newNode->left =  build(inorder, start1, k - 1, postorder,   
  17.                     start2, end2 - end1 + k - 1);  
  18.         return newNode;  
  19.     }  
  20. };  

14、编号108 Binary Tree Level Order Traversal IIGiven a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root).
For example: Given binary tree {3,9,20,#,#,15,7},
    3
   / \
  9  20
    /  \
   15   7
return its bottom-up level order traversal as:
[
  [15,7]
  [9,20],
  [3],
]
上面出现过的某一题的第二次变种。这次不是从上向下打印,也不是从右往左打印,而是要从下往上输出结果。取巧的结果是,在获得最后结果后,反向交换。。。
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     vector<vector<int> > levelOrderBottom(TreeNode *root) {  
  4.         vector<vector<int>> result;  
  5.         if(root == NULL) return result;  
  6.           
  7.         queue<TreeNode*> q;  
  8.         queue<int> queue_level;  
  9.         q.push(root);   
  10.         queue_level.push(0);  
  11.           
  12.         vector<int> elem;  
  13.         result.push_back(elem);  
  14.           
  15.         while(q.size() > 0){  
  16.             TreeNode* x = q.front();  
  17.             q.pop();  
  18.             int l = queue_level.front();  
  19.             queue_level.pop();  
  20.               
  21.             if(l > (result.size()-1) ){  
  22.                 vector<int> elem;  
  23.                 result.push_back(elem);  
  24.             }  
  25.             result[l].push_back(x->val);  
  26.               
  27.             if(x->left != NULL){  
  28.                 q.push(x->left);  
  29.                 queue_level.push(l+1);  
  30.             }  
  31.               
  32.             if(x->right != NULL){  
  33.                 q.push(x->right);  
  34.                 queue_level.push(l+1);  
  35.             }  
  36.         }  
  37.           
  38.         /*only difference*/  
  39.         for(int i = 0; i < result.size() / 2; i++) Swap(result[i], result[result.size()-1-i]);  
  40.           
  41.         return result;  
  42.     }  
  43.       
  44.     /*only difference*/  
  45.     void Swap(vector<int> &x, vector<int> &y){  
  46.         vector<int> tmp = x;  
  47.         x = y;  
  48.         y = tmp;  
  49.     }  
  50. };  

15、编号109 Convert Sorted Array to Binary Search Tree

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

平衡二叉查找树的特点是,除了满足BST的基本特点,另外对于任意一个结点,它左子树和右子树的深度最大差1。所以不同用中间结点做每一步的根结点,递归就可以了。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     TreeNode *sortedArrayToBST(vector<int> &num) {    
  4.         return BuildTree(num, 0, num.size()-1);    
  5.     }    
  6.       
  7.     TreeNode *BuildTree(vector<int> &num, int start, int end)    
  8.     {    
  9.         if(start > end) return NULL;    
  10.         if(start == end) return new TreeNode(num[start]);    
  11.         int mid = (start + end) / 2;    
  12.         TreeNode *node = new TreeNode(num[mid]);    
  13.         node->left = BuildTree(num, start, mid-1);    
  14.         node->right = BuildTree(num, mid+1, end);    
  15.         return node;    
  16.     }    
  17. };  

16、编号110 Convert Sorted List to Binary Search Tree

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

和上题一样递归就可以了。但是linked list不能像数组一样index任意数据,所以不能够自顶向下建立树。下面的方法是一个特别的自底向顶的递归方法。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     TreeNode *sortedListToBST(ListNode *head) {    
  4.         int len = 0;    
  5.         ListNode *p = head;    
  6.         while(p){ /*Get the length*/  
  7.             len++;    
  8.             p = p->next;    
  9.         }    
  10.         return BuildBST(head, 0, len-1);    
  11.     }    
  12.       
  13.     TreeNode* BuildBST(ListNode* &list, int start, int end) {    
  14.       if (start > end) return NULL;  
  15.         
  16.       int mid = (start + end) / 2;   
  17.         
  18.       TreeNode *leftChild = BuildBST(list, start, mid-1);    
  19.         
  20.       TreeNode *parent = new TreeNode(list->val);    
  21.       parent->left = leftChild;    
  22.       list = list->next;    
  23.         
  24.       parent->right = BuildBST(list, mid+1, end);    
  25.       return parent;    
  26.     }    
  27. };  

17、编号111 Balanced Binary Tree

Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

和上面两题一样,注意每个结点都要判断它的左右子树。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     bool isBalanced(TreeNode *root) {    
  4.         if(root == NULL) return true;    
  5.         
  6.         int diff = GetDiff(root);    
  7.         if(diff == -1) return false;  /*-1 denotes unbalance*/  
  8.         return true;        
  9.     }      
  10.     int GetDiff(TreeNode* node){    
  11.       if(node == NULL) return 0;    
  12.         
  13.       int left = GetDiff(node->left);    
  14.       if(left == -1) return -1;    
  15.       int right = GetDiff(node->right);    
  16.       if(right == -1) return -1;   
  17.         
  18.       if(left-right>1 || right-left>1)  return -1;    
  19.       return left>right? left+1:right+1;    
  20.     }  
  21. };  

18、编号112 Minimum Depth of Binary Tree

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

跟找最大深度一样,把变量当递归参数调用下去。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     int minDepth(TreeNode *root) {  
  4.         if(root == NULL) return 0;  
  5.         int min = INT_MAX;  
  6.         Recursion(root, 1, min);  
  7.         return min;  
  8.     }  
  9.       
  10.     void Recursion(TreeNode *root, int level, int &min){  
  11.         if(root->left == NULL && root->right == NULL)  
  12.             if(level < min) min = level;  
  13.         if(root->left != NULL) Recursion(root->left, level+1, min);  
  14.         if(root->right != NULL) Recursion(root->right, level+1, min);  
  15.    
  16.     }  
  17. };  

19、编号113 Path Sum

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.

跟上题一个思路。。。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     bool hasPathSum(TreeNode *root, int sum) {  
  4.         if(root == NULL) return false;  
  5.         return Recursion(root, 0, sum);  
  6.     }                                
  7.       
  8.     bool Recursion(TreeNode *root, int num, int sum){  
  9.         int newNum = num + root->val;  
  10.           
  11.         if(root->left == NULL && root->right == NULL){  
  12.             if(newNum == sum) return true;  
  13.             return false;  
  14.         }  
  15.           
  16.         if(root->left != NULL  && Recursion(root->left,  newNum, sum)) return true;  
  17.         if(root->right != NULL && Recursion(root->right, newNum, sum)) return true;  
  18.           
  19.         return false;  
  20.           
  21.     }  
  22. };  

20、编号114 Path Sum II

Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.
For example: Given the below binary tree and sum = 22,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1
return
[
   [5,4,11,2],
   [5,8,4,5]
]

又跟上题一个思路。。。只不过输出结构不同。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     vector<vector<int> > pathSum(TreeNode *root, int sum) {  
  4.         vector<vector<int>> result;  
  5.         if(root == NULL) return result;  
  6.         vector<int> oneResult;  
  7.         Recursion(root, 0, sum, oneResult, result);  
  8.         return result;  
  9.     }  
  10.       
  11.     void Recursion(TreeNode *root, int num, int sum,   
  12.                 vector<int> oneResult, vector<vector<int>> &result){  
  13.         int newNum = num + root->val;  
  14.         oneResult.push_back(root->val);  
  15.           
  16.         if(root->left == NULL && root->right == NULL)  
  17.             if(newNum == sum) result.push_back(oneResult);  
  18.           
  19.         if(root->left!=NULL)  
  20.             Recursion(root->left, newNum, sum, oneResult, result);  
  21.               
  22.         if(root->right!=NULL)  
  23.             Recursion(root->right, newNum, sum, oneResult, result);  
  24.           
  25.     }  
  26. };  

21、编号115 Flatten Binary Tree to Linked List

Given a binary tree, flatten it to a linked list in-place.
For example, Given
         1
        / \
       2   5
      / \   \
     3   4   6
The flattened tree should look like:
   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6
click to show hints.
Hints: If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order traversal.

改变树的结构是有点难的一类题。看不出规律的话就会觉得完全没有思路。解法还是递归。规律是每个结点左边必须是NULL,右边是:若用后续遍历树,则右边指针指向上一个处理的结点。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     void flatten(TreeNode *root) {  
  4.         TreeNode *lastRoot = NULL;  
  5.         Recursion(root, lastRoot);  
  6.     }  
  7.       
  8.     void Recursion(TreeNode *root, TreeNode *&lastRoot){  
  9.         if(root == NULL) return;  
  10.           
  11.         Recursion(root->right, lastRoot);  
  12.         Recursion(root->left, lastRoot);  
  13.           
  14.         root->right = lastRoot;  
  15.         lastRoot = root;  
  16.           
  17.         root->left = NULL;  
  18.     }  
  19. };  

22、编号117 Populating Next Right Pointers in Each Node

23、编号120 Populating Next Right Pointers in Each Node II

Given a binary tree
    struct TreeLinkNode {
      TreeLinkNode *left;
      TreeLinkNode *right;
      TreeLinkNode *next;
    }
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
Initially, all next pointers are set to NULL.
Note: You may only use constant extra space.
You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).
For example, Given the following perfect binary tree,
         1
       /  \
      2    3
     / \  / \
    4  5  6  7
After calling your function, the tree should look like:
         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \  / \
    4->5->6->7 -> NULL

另一道改变树的结构的难题。把编号117和编号120列在一起是因为120除了输入数据不是perfect binary tree外,其它的条件都一样。在网上有同时通过两道题的答案,看看吧。。。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     void connect(TreeLinkNode *root) {  
  4.         while(root != NULL){  //Loop 1  
  5.             TreeLinkNode *pre = NULL;  
  6.             TreeLinkNode *next = NULL;  
  7.               
  8.             while(root != NULL){ //Loop 2  
  9.                 if(root->left == NULL && root->right == NULL) {  
  10.                     root = root->next;  
  11.                     continue;  
  12.                 }  
  13.                   
  14.                 if(next == NULL) next = root->left ? root->left : root->right;  
  15.                   
  16.                 if(root->left){  
  17.                     if(pre) pre->next = root->left;  
  18.                     pre = root->left;  
  19.                 }  
  20.                 if(root->right){  
  21.                     if(pre) pre->next = root->right;  
  22.                     pre = root->right;  
  23.                 }  
  24.                   
  25.                 root = root->next;  
  26.             }  
  27.               
  28.             root = next;  
  29.         }  
  30.           
  31.     }  
  32. };  

24、编号125 Binary Tree Maximum Path Sum

Given a binary tree, find the maximum path sum.
The path may start and end at any node in the tree.
For example: Given the below binary tree,
       1
      / \
     2   3
Return 6

跟以前一样,把答案放参数里面递归就可以了。唯一小心的是这个path可以以任何点为起点和终点(不只是根结点和叶子)

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     /*Recursive*/  
  4.     int maxPathSum(TreeNode *root) {  
  5.         if(root == NULL) return 0;  
  6.           
  7.         int maxValue = -INT_MAX; /*Do not use maxValue here*/  
  8.           
  9.         int v = root->val;  
  10.         int l = Recursion(root->left, maxValue);  
  11.         int r = Recursion(root->right, maxValue);  
  12.               
  13.         //return:v, (l, r,) l+v, v+r, l+v+r, maxValue  
  14.         int returnValue = -INT_MAX;  
  15.         returnValue = max(returnValue, v);  
  16.         returnValue = max(returnValue, l+v);  
  17.         returnValue = max(returnValue, v+r);  
  18.         returnValue = max(returnValue, l+v+r);  
  19.         returnValue = max(returnValue, maxValue);  
  20.         return returnValue;  
  21.          
  22.     }  
  23.       
  24.     int Recursion(TreeNode *root, int &maxValue){  
  25.         if(root == NULL) return 0;  
  26.           
  27.         int v = root->val;  
  28.         int l = Recursion(root->left, maxValue);  
  29.         int r = Recursion(root->right, maxValue);  
  30.    
  31.         //maxValue:v, (l, r,) l+v, v+r, l+v+r  
  32.         maxValue = max(maxValue, v);  
  33.         maxValue = max(maxValue, l+v);  
  34.         maxValue = max(maxValue, v+r);  
  35.         maxValue = max(maxValue, l+v+r);  
  36.           
  37.         //return: v, l+v, v+r  
  38.         return max(max(l+v, v+r), v);  
  39.     }  
  40. };  

25、编号130 Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.
An example is the root-to-leaf path 1->2->3 which represents the number 123.
Find the total sum of all root-to-leaf numbers.
For example,
    1
   / \
  2   3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Return the sum = 12 + 13 = 25.

又是自顶向下递归(递归得要吐了有木有!)

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     int sumNumbers(TreeNode *root) {  
  4.         if(root == NULL) return 0;  
  5.           
  6.         int result = 0;  
  7.           
  8.         if(root->left == NULL && root->right == NULL)    
  9.             return root->val;  
  10.           
  11.         GetSum(root->left, root->val, result);  
  12.         GetSum(root->right, root->val, result);  
  13.           
  14.         return result;  
  15.     }  
  16.       
  17.     void GetSum(TreeNode *root, int num, int &result){  
  18.         if(root == NULL) return;  
  19.           
  20.         if(root->left == NULL && root->right == NULL){  
  21.             result += num*10 + root->val;  
  22.             return;  
  23.         }  
  24.           
  25.         GetSum(root->left, num*10 + root->val, result);  
  26.         GetSum(root->right, num*10 + root->val, result);  
  27.     }  
  28. };  

26、编号145 Binary Tree Preorder Traversal

Given a binary tree, return the preorder traversal of its nodes' values.
For example: Given binary tree {1,#,2,3},
   1
    \
     2
    /
   3
return [1,2,3].
Note: Recursive solution is trivial, could you do it iteratively?

跟编号97一个类型的题。97是中序,这个是前序。先给个简单的递归吧

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. vector<int> preorderTraversal(TreeNode *root) {  
  2.         vector<int> result;  
  3.         Recursion(root, result);  
  4.         return result;  
  5.     }  
  6.       
  7.     void Recursion(TreeNode *root, vector<int> &result){  
  8.         if(!root) return;  
  9.         result.push_back(root->val);  
  10.         Recursion(root->left, result);  
  11.         Recursion(root->right, result);  
  12.     }  
下面是非递归。
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     /*Iterative*/  
  4.     vector<int> preorderTraversal(TreeNode *root) {  
  5.         vector<int> result;  
  6.         if(!root) return result;  
  7.           
  8.         stack<TreeNode*> s;  
  9.         s.push(root);  
  10.           
  11.         while(!s.empty()){  
  12.             TreeNode* n = s.top();  
  13.             result.push_back(n->val);  
  14.             s.pop();  
  15.               
  16.             if(n->right) s.push(n->right);  
  17.             if(n->left) s.push(n->left);  
  18.         }  
  19.           
  20.           
  21.         return result;  
  22.     }  
  23. };  


27、编号146 Binary Tree Postorder Traversal
Given a binary tree, return the postorder traversal of its nodes' values.
For example: Given binary tree {1,#,2,3},
   1
    \
     2
    /
   3
return [3,2,1].
Note: Recursive solution is trivial, could you do it iteratively?

有中序和前序了,这个就是后序法。后续是 左-右-中,倒过来是 中-右-左。先处理中结点比较容易。最后再反过来就好了。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     vector<int> postorderTraversal(TreeNode *root) {  
  4.         vector<int> result;  
  5.         if(root == NULL) return result;  
  6.           
  7.         stack<TreeNode *> s;  
  8.         s.push(root);  
  9.           
  10.         while(!s.empty()){  
  11.             TreeNode *n = s.top();  
  12.             result.push_back(n->val);  
  13.             s.pop();  
  14.               
  15.             if(n->left != NULL)  s.push(n->left);  
  16.             if(n->right != NULL) s.push(n->right);  
  17.         }  
  18.           
  19.         reverse(result.begin(), result.end());  
  20.           
  21.         return result;  
  22.     }  
  23. };  

1 0
原创粉丝点击