LeetCode初级算法(树篇)

二叉树的最大深度

二叉树,所以可以考虑用递归来做。由于根节点已经算过了,所以需要加上1;每次返回都是以递归时的节点作为根节点进行判断的最大深度。还是比较好理解,代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(root==NULL) return 0;
        int LeftSize=1+maxDepth(root->left);
        int RightSize=1+maxDepth(root->right);
        return max(LeftSize,RightSize);
    }
};

在网上还看到了有人用队列来做,附代码如下:

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(!root) return 0;
        int res=0;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()){
            ++res;
            int n=q.size();
            for(int i=0;i<n;++i)
            {
                TreeNode *t=q.front();q.pop();
                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }
        }
        return res;
    }
};

这个方法也是非常的巧妙!利用队列来存储每一个要处理的节点,处理之前先记一次数res,处理时从队列中拿出来,专门处理这个节点,如果这个节点是子节点,不执行操作;如果不为子节点,在队列中存储它的左右节点,在下一次循环中先取左节点再取右节点进行处理。

验证二叉搜索树

这道题没什么思路,开始想用和上一道题一样的递归的解法,发现不得行。直接看了大神的代码:

// Recursion without inorder traversal
class Solution {
public:
    bool isValidBST(TreeNode *root) {
        return isValidBST(root, LONG_MIN, LONG_MAX);
    }
    bool isValidBST(TreeNode *root, long mn, long mx) {
        if (!root) return true;
        if (root->val <= mn || root->val >= mx) return false;
        return isValidBST(root->left, mn, root->val) && isValidBST(root->right, root->val, mx);
    }
};

他这样的解法是重载了一个新的isValidBST函数,用自己需要的参数进行判断(还有此等操作??!!)然后利用return isValidBST(root->left, mn, root->val) && isValidBST(root->right, root->val, mx);进行递归判断,而判断语句也写得非常的巧妙if (root->val <= mn || root->val >= mx) return false;。首先每次递归的时候会判断语句中的两个判断条件的一个是否满足条件,就是判断root->left与root进行比较或者将root->right与root进行比较,而另外一个条件则是由于传送了参数LONG_MIN,与LONG_MAX,所以这部分条件是始终满足的。而实现这么巧妙的一个判断语句能分情况的处理条件是和我们传送参数的顺序有关的,比如isValidBST(root->left, mn, root->val)isValidBST(root->right, root->val, mx)两个参数的顺序不一致,所以可以实现这么巧妙的变化。

此外网上还有其他解法:

public class Solution {  
    /** 
     * @param root: The root of binary tree. 
     * @return: True if the binary tree is BST, or false 
     */  
    public int lastVal = Integer.MAX_VALUE;  
    public boolean firstNode = true;  
    public boolean isValidBST(TreeNode root) {  
        // write your code here  
        if(root == null){  
            return true;  
        }  
        if(!isValidBST(root.left)){  
            return false;  
        }  
        if(!firstNode && lastVal >= root.val){  
            return false;  
        }  
        //此时 root.val>=lastval 是右子树  
        firstNode = false;  
        lastVal = root.val;  
        if(!isValidBST(root.right)){  
            return false;  
        }  
        return true;  
    }  
}  

这段代码里是用lastVal来存储目前处理的上一个根节点的值,firstNode来判断现在处理的是左子树还是右子树。这道题还是挺有难度的。

对称二叉树

利用队列,检测左节点的左节点与右节点的右节点、左节点的右节点与右节点的左节点是否相等。循环的条件为队列中有元素,没有元素就代表所有结点都判断完了,返回true;中途如果有不满足判断条件,就直接返回false。值得一提的是,while循环中创建了两个新节点node1与node2,分别存储各自根节点的左或右子节点,看代码就应该比较好理解:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root==NULL) return true;
        queue<TreeNode *>q1,q2;
        q1.push(root->left);
        q2.push(root->right);
        
        while(!q1.empty() && !q2.empty())
        {
            TreeNode *node1=q1.front();
            TreeNode *node2=q2.front();
            q1.pop();q2.pop();
            if((node1==NULL && node2!=NULL) || (node1!=NULL && node2==NULL))
               return false;
            if(node1!=NULL && node2!=NULL)
               {
                   if(node1->val!=node2->val)
                       return false;
                   else
                   {
                       q1.push(node1->left);
                       q2.push(node2->right);
                       q1.push(node1->right);
                       q2.push(node2->left);
                   }
               }
        }
        return true;
    }
};

然后,这里再贴出大神的重载函数代码:

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        return isSymmetric(root->left,root->right);
    }
    bool isSymmetric(TreeNode *left,TreeNode *right){
        if(!left && !right) return true;
        if((left && !right) || (!left && right) || (left->val!=right->val)) return false;
        return isSymmetric(left->left,right->right) && isSymmetric(left->right,right->left);
    }
};

二叉树的层次遍历

    /** 
     * Definition for a binary tree node. 
     * struct TreeNode { 
     *     int val; 
     *     TreeNode *left; 
     *     TreeNode *right; 
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} 
     * }; 
     */  
    class Solution {  
    public:  
        //二叉树层次遍历 通过队列BFS广度优先搜索  
        vector<vector<int>> levelOrder(TreeNode* root) {  
            vector<vector<int>> result;  
            queue<TreeNode*>q;              
            vector<int> level;       //每层结果  
            int size,i;  
            TreeNode* p;  
              
            if(root==NULL) return result;  
            q.push(root);            //入队  
            while(!q.empty()) {  
                //队列中有几个元素就依次遍历每个元素的左右结点  
                level.clear();  
                size=q.size();  
                for(i=0; i<size; i++) {  
                    p=q.front();     //队首元素值赋给p  
                    q.pop();         //出队  
                    level.push_back(p->val);  
                    if(p->left) {    //依次压入左右结点元素  
                        q.push(p->left);  
                    }  
                    if(p->right) {  
                        q.push(p->right);  
                    }  
                }  
                result.push_back(level);   //添加每层数据  
            }  
            return result;  
        }  
    };  

将有序数组转换为二叉搜索树

平衡二叉树的根节点的值为数组中的中间值,即中序遍历时,根结点位于正中间;所以使用二分法,先把有序数组的最中间值设为根结点,然后根结点的左孩子是左半段数组的最中间值,根结点的右孩子是右半段数组的最中间值。依次这样,即可以建立一个平衡二叉搜索树。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return sortedArrayToBST(nums,0,nums.size()-1);
    }
    
    TreeNode* sortedArrayToBST(vector<int> &nums,int begin ,int end){
        if(begin>end)
            return NULL;
        int mid=(begin+end)/2;
        TreeNode* root=new TreeNode(nums[mid]);   //根结点,为当前数组的中间值
         root->left = sortedArrayToBST(nums , begin , mid - 1);//根结点的左孩子为左半段数组的中间值  
        root->right = sortedArrayToBST(nums , mid + 1 , end);//根结点的右孩子为右半段数组的中间值  
        return root;  
    }
};
posted @ 2018-04-23 20:15  MrYun  阅读(224)  评论(0编辑  收藏  举报