zoukankan      html  css  js  c++  java
  • leetcode 刷题日志 2018-3-28

    树:

    404. 左叶子之和

    求所有左叶子结点之和
    1. 递归法
    分析:递归法遍历结点,找左叶子结点
            空指针判断
            有左子节点?是叶子结点?是的话更新value的值
    
    int sumOfLeftLeaves(TreeNode* root) {
            if(!root) return 0; // NULL 
            int value = 0;
            if(root->left){ //左子节点
                    if(!root->left->left && !root->left->right) //是不是叶子结点?
                            value = root->left->val ;
            }
            return value + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
    }
    

    2.非递归法遍历寻找所有左叶子结点 int sumOfLeftLeaves(TreeNode* root) { if(!root) return 0; //注意一定要处理空指针 int res = 0; queue<TreeNode*> q; q.push(root); while(!q.empty()){ root = q.front(); q.pop(); if(root->left){ //左子节点 q.push(root->left); if(!root->left->left && !root->left->right){ //是否为叶子结点 res += root->left->val; } } if(root->right){ q.push(root->right); } } return res; }

    671. Second Minimum Node In a Binary Tree

    题意:求二叉树第二小值,没有返回-1
    分析:用set存所有节点,最终容量大于2,代表存在第二小值,输出*(++set.begin())
    ```
    int findSecondMinimumValue(TreeNode* root) {
                if(!root) return -1;
                int res = -1;
                queue<TreeNode* > q;
                q.push(root);
                set<int> s;
                while (!q.empty())
                {
                        root = q.front();
                        s.insert(root->val);
                        q.pop();
                        if (root->left) {
                                q.push(root->left);
                        }
                        if (root->right) {
                                q.push(root->right);
                        }
                }
                if(s.size() < 2) res = -1;
                else res = *(++s.begin());
                return res;
    }

     102. 二叉树的层次遍历

    二叉树层次遍历且每层输出
    算法记忆:一层一循环
    ```
    vector<vector<int>> levelOrder(TreeNode* root) {
            vector<vector<int> > res;
            vector<int> tmp;
            if(!root) return res;
            queue<TreeNode*> q;
            q.push(root);
            int currentLevelTotalNum = 0;
            while(!q.empty())
            {
                tmp.clear();
                currentLevelTotalNum = q.size();
                while(currentLevelTotalNum--){  //一层一循环
                    root = q.front();
                    tmp.push_back(root->val);
                    q.pop();
                    if(root->left){
                        q.push(root->left);
                    }
                    if(root->right){
                        q.push(root->right);
                    }
                }
                res.push_back(tmp);
            }
            return res;
        }
    ```

    107. 二叉树的层次遍历 II

    分析:在正序层析遍历基础上,用栈临时存一下

    vector<vector<int>> levelOrderBottom(TreeNode* root) {
            vector<vector<int> > res;
            vector<int> tmp;
            stack<vector<int> >tmps;
            if(!root) return res;
            queue<TreeNode*> q;
            q.push(root);
            int currentLevelTotalNum = 0;
            while(!q.empty())
            {
                tmp.clear();
                currentLevelTotalNum = q.size();
                while(currentLevelTotalNum--){  //一层一循环
                    root = q.front();
                    tmp.push_back(root->val);
                    q.pop();
                    if(root->left){
                        q.push(root->left);
                    }
                    if(root->right){
                        q.push(root->right);
                    }
                }
                tmps.push(tmp);
            }
            while(!tmps.empty()){
                res.push_back(tmps.top());
                tmps.pop();
            }
            return res;
        }

     637. 二叉树的层平均值

    题意:求二叉树每层平均值(double)所组成的数组
    分析:每层求和取平均值
    ```
    vector<double> averageOfLevels(TreeNode* root) {
            vector<double> res;
            if(!root) return res;
            queue<TreeNode* > q;
            q.push(root);
            int currentLevelTotalNum = 0, n = 0;
            double tmpd;
            while(!q.empty()){
                currentLevelTotalNum = q.size();
                n = currentLevelTotalNum;
                tmpd = 0;
                while(currentLevelTotalNum--){ //此层所有节点
                    root = q.front();
                    tmpd +=root->val;
                    q.pop();
                    if(root->left){
                        q.push(root->left);
                    }
                    if(root->right)
                    {
                        q.push(root->right);
                    }
                }
                tmpd /= n;
                res.push_back(tmpd);
            }
            return res;
        }
    ```

     101. 对称二叉树

    关键点在于递归比较。

    题意:给定一个二叉树,检查它是否是它自己的镜像(即,围绕它的中心对称)。
    分析:一个结点左子节点l,与右子节点r比较,递归的判断整棵树,l的左与r的右 且l的右跟r的左比较
    抽取出递归模型如下
    ```
    bool is(TreeNode* root1, TreeNode* root2){
            if(!root1 && !root2) return true;
            if(!root1) return false;
            if(!root2) return false;
            if(root1->val != root2->val){
                return false;
            }
            return is(root1->left,root2->right) && is(root1->right,root2->left);
        }
        bool isSymmetric(TreeNode* root) {
            if(!root) return true;
            return is(root->left,root->right);
        }
    ```

     111. 二叉树的最小深度

    题意:二叉树最小深度(从根节点到叶子结点的结点个数,包含两端)
    分析:递归,
    终结条件是 1. root ==NULL 0  2. 叶子结点 1
    分别计算左子树、右子树的长度
    取最小值,因为加上本结点所以最终返回值+1
    ```
    int minDepth(TreeNode* root) {
            if(!root) return 0;
            if(!root->left && !root->right)
                return 1;
            int left,right;
            if(root->left) left = minDepth(root->left);
            else left = INT_MAX;
            if(root->right) right = minDepth(root->right);
            else right = INT_MAX;
            return min(left,right) + 1;
        }
    ```

     104. 二叉树的最大深度

    题意:最大二叉树深度
    分析:递归法
    1.终结条件:
            1. NULL 0
            2. 叶子结点 1
    2. 分别计算左右子树长度
    3. 返回max(left,right)+1 加1是因为加上本结点
    ```
    int maxDepth(TreeNode* root) {
            if(!root) return 0;
            if(!root->left && !root->right) return 1;
            int left, right;
            if(root->left) left = maxDepth(root->left);
            else left = INT_MIN;
            if(root->right) right = maxDepth(root->right);
            else right = INT_MIN;
            return max(left,right) + 1;
        }
    ```

    110. 平衡二叉树

    题意:判断是否为平衡二叉树
    分析:
    本题是递归数深度遍历的一种应用。按照题目的意思,对于一个节点分别算出每个节点的左、右子树的深度,如果左、右子树深度差大于1,则可以该树非平衡。
    那么递归每一个节点,一旦发现某一节点非平衡,就返回false,如果每一节点都平衡,则返回true: ```
    //获取树的深度 int getDepth(TreeNode* root){ if(!root) return 0; return max(getDepth(root->left),getDepth(root->right)) + 1; } //递归判断每个结点的子树是否满足长度只差不大于1 bool isBalanced(TreeNode* root) { if(!root) return true; if(abs(getDepth(root->left) - getDepth(root->right)) > 1){ return false; } return isBalanced(root->left) && isBalanced(root->right); } ```

     144. 二叉树的前序遍历 +1 2

    题目:二叉树,前序遍历,迭代法

    分析:DFS,用到栈,一直沿着左指针将沿路节点压入栈内,当到尽头,弹出top结点,将其右子树压入,右子树同样是先沿着左指针压到尽头后,向右展

    记忆:深搜栈右展

    ```
    vector<int> res;
        vector<int> preorderTraversal(TreeNode* root) {
            //递归
            if(root){
                res.push_back(root->val);
                preorderTraversal(root->left);
                preorderTraversal(root->right);
            }   return res;
    }
    
    vector<int> preorderTraversal(TreeNode* root) {
                //迭代
                vector<int> res;
                if(!root) return res;
                stack<TreeNode*> s;
                while (!s.empty() || root != NULL)
                {
                        if (root) { //至最左
                                res.push_back(root->val);
                                s.push(root);
                                root = root->left;
                        } else { //左到尽头,往右走
                                root = s.top();
                                s.pop();
                                root = root->right;
                        }
                }
                return res;
        }
    
    
    
    ```

     94. 中序遍历二叉树 1+2

    题意: 二叉树中序遍历,迭代法

    分析: DFS,利用栈,沿着左指针将一直到最左端的沿路所有节点依次压入栈中,每到到最左端向右展一下

    记忆:深搜栈右展

    ```
    vector<int> inorderTraversal(TreeNode* root) {
                stack< TreeNode* > s;
                TreeNode * p = root;
                vector<int> tmp;
                while(!s.empty() || p!=NULL){
                        while(p){ //到最左端
                                s.push(p);
                                p=p->left;
                        }
                        if(!s.empty()){  //右展一次
                                p=s.top();
                                tmp.push_back(p->val);
                                s.pop();
                                p=p->right;
                        }
                }
                return tmp;
        }
    
    
    ```

     145. 二叉树的后序遍历 1 2 + 迭代法

    分析:同样用到栈

    记忆:+21入栈,处理两情况

    //递归法
    ```
    vector<int> res;
        vector<int> postorderTraversal(TreeNode* root) {
            if(root){
                postorderTraversal(root->left);
                postorderTraversal(root->right);
                res.push_back(root->val);
            }
            return res;
        }
    ```
    //迭代法
    ```
    vector<int> postorderTraversal(TreeNode* root) {
            vector<int> res;
            if(!root) return res;
            stack<TreeNode* > s;
            TreeNode *cur = root, *pre = NULL;
            s.push(cur);
            // 栈中的顺序是后序遍历的反序,先压入根,再压入右结点,左结点
            while (!s.empty())
            {
                cur = s.top();
                if((!cur->left && !cur->right) || (pre && (cur->left == pre || cur->right == pre))) //叶子结点直接处理 || 刚刚处理完左右结点
                {
                    res.push_back(cur->val);
                    pre = cur;
                    s.pop();
                }
                else{
                    if(cur->right){
                        s.push(cur->right);
                    }
                    if (cur->left)
                        s.push(cur->left);
                }
            }
            return res;
        }
    ```

     617. 合并二叉树

    /*
    题意:合并两棵二叉树,对应结点相加,否则补上
    分析:递归实现
                    根节点都为空,return NULL
                    根节点都不为空,求和
                    根节点有一个空,补上
                    进一步分析左右子树
    前三步就是抽取出来的子过程
    */
    ```
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
            if(!t1 && !t2) return NULL;
            if (t1 && t2) {
                t1->val += t2->val;
                t2->val = t1->val;
            }
            else if (t1) {
                t2 = new TreeNode(t1->val);
            }
            else if (t2) {
                t1 = new TreeNode(t2->val);
            }
            t1->left = mergeTrees(t1->left,t2->left);
            t1->right = mergeTrees(t1->right,t2->right);
            return t1;
        }
    ```

     114. 二叉树转换链表

    题意:二叉树转换链表;将所有结点编程右指针连接
    分析:将前序遍历序列,顺序串联
    
    ```
    //迭代版,前序遍历
        vector<TreeNode*> preOrder2(TreeNode* root) {
            vector<TreeNode*> res;
            if(!root) return res;
            stack<TreeNode*> s;
            TreeNode* p = root;
            while(!s.empty() || p)
            {
                while(p){   //一直往左
                    res.push_back(p);
                    s.push(p);
                    p = p->left;
                }
                if(!s.empty()){ //右展
                    p = s.top();
                    s.pop();
                    p = p->right;
                }
            }
            return res;
        }
        // 注意只需保留头指针,指针传递,传递方保留着头指针,他顺着访问就是了
        void flatten(TreeNode* root) {
            if(!root) return ;
            //前序遍历结果
            vector<TreeNode*> preOrderV = preOrder2(root);
            int len = preOrderV.size();
            root->left = NULL;
            root->right = NULL;
            //链表形成
            for(int i=0;i<len;i++)
            {
                root->right = preOrderV[i];
                root = preOrderV[i];
                root->left = NULL;
                root->right =NULL;
            }
        }
    ```

     112. 路径总和

    /*
    题意:路径总和,给一棵二叉树和一个整数sum,问是否存在从根节点到叶节点的路径,求和等于sum
    分析:递归,和递减
    */
    ```
    bool hasPathSum(TreeNode* root, int sum) {
            if(!root) return false;
            if(root->val == sum){ //恰好有叶节点满足
                if(!root->left && !root->right){
                    return true;
                }
            }
            return hasPathSum(root->left,sum-root->val) || hasPathSum(root->right,sum-root->val);
        }
    ```

     113. 路径总和 II

    题意:找出一棵二叉树里,路径(根结点到叶结点)上结点之和等于sum的所有路径

    分析:经典递归回溯问题,搜集路径上所有节点时,注意遇到结点push,用完节点pop

    经典递归回溯
    ```
    vector<vector<int> >result;
        vector<int> path;
        // 经典递归回溯问题
        void findPath(TreeNode* root, int sum) {
            if(!root) return ;
            if(root->val == sum && !root->left && !root->right ) { //find a path equal sum && It's a leaf node 
                path.push_back(root->val);
                result.push_back(path); // find a path
                path.pop_back(); //!!
                return ;
            }
            path.push_back(root->val); // 经过节点压入
            findPath(root->left, sum - root->val);
            findPath(root->right, sum - root->val);
            path.pop_back(); // 对与此节点的左右子树都已经处理完,弹出此节点 !
        }
        vector<vector<int>> pathSum(TreeNode* root, int sum) {
            vector<vector<int>> res;
            if(!root) return res;
            findPath(root, sum);
            return result;
        }
    ```

     257. 二叉树的所有路径

    /*
    题意:输出二叉树所有路径
    分析:经典递归回溯法
    */
    ```
    vector<vector<int> >allPath; //所有路径
        vector<int> aPath; //单条路径
        // 经典递归回溯法求二叉树所有路径
        void findPath(TreeNode* root) {
            if(!root) return ;
            if(!root->left && !root->right) { //leaf node
                aPath.push_back(root->val);
                allPath.push_back(aPath);   // a path
                aPath.pop_back();
                return ;
            }
            aPath.push_back(root->val);
            findPath(root->left);
            findPath(root->right);
            aPath.pop_back();
        }
        
        vector<string> binaryTreePaths(TreeNode* root) {
            vector<string> res;
            if(!root) return res;
            findPath(root);
            int len = allPath.size();
            string tmpS = "";
            for (int i=0; i<len; i++) {
                tmpS = std::to_string(allPath[i][0]);
                for (int j=1; j<allPath[i].size(); j++) {   //形成路径字符串
                    tmpS += ("->" + std::to_string(allPath[i][j]));
                }
                res.push_back(tmpS);
            }
            return res;
        }
    ```
  • 相关阅读:
    图像全參考客观评价算法比較
    单片机project师必备的知识
    ACM-并查集之小希的迷宫——hdu1272
    ArcGIS教程:加权总和
    九度 题目1368:二叉树中和为某一值的路径
    解决solr搜索多词匹配度和排序方案
    具体解释linux文件处理的的经常使用命令
    Hotel
    Unity3D 射线指定层获取GameObject 注意 LayerMask
    ios设计一部WindowsPhone手机
  • 原文地址:https://www.cnblogs.com/kimsimple/p/8662450.html
Copyright © 2011-2022 走看看