leetcode算法刷题的第十四天

1.leetcode 513.找树左下角的值

题目链接

这道题如果用递归法的话,可能会比较难,但是如果用迭代法里面的层序遍历,那就非常简单了,甚至可以套用模板并加以修改一点点就行了。

第一种解法:递归法

咋眼一看,这道题目用递归的话就就一直向左遍历,最后一个就是答案呗?

没有这么简单,一直向左遍历到最后一个,它未必是最后一行啊。

我们来分析一下题目:在树的最后一行找到最左边的值

首先要是最后一行,然后是最左边的值。

如果使用递归法,如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int maxDepth=INT_MIN;
    int result=0;
    void traversal(TreeNode* node,int depth){
        if(node->left==NULL&&node->right==NULL){
            if(depth>maxDepth){
                maxDepth=depth;
                result=node->val;
            }
            return;
        }
        if(node->left){
            traversal(node->left,depth+1);
        }
        if(node->right){
            traversal(node->right,depth+1);
        }
        return;
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root,0);
        return result;
    }
};

第二种解法:迭代法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        int result=0;
        if(root==NULL) return 0;
        que.push(root);
        while(!que.empty()){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode* node=que.front();
                que.pop();
                if(i==0) result=node->val;
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }
        return result;
    }
};

2.leetcode 112.路径总和

题目链接

这道题用的是递归法,用的是深度优先搜索,这道题用前中后序遍历其实都可以。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public://count如果为0,就表示找到了符合条件的路径
    bool traversal(TreeNode* current,int count){
        //遇到叶子节点
        if(current->left==NULL&&current->right==NULL&&count==0) return true;
        if(current->left==NULL&&current->right==NULL&&count!=0) return false;

        if(current->left){
            count-=current->left->val;//递归,处理节点
            if(traversal(current->left,count)) return true;
            count+=current->left->val;//回溯,撤销处理结果
        }
        if(current->right){
            count-=current->right->val;//递归,处理节点
            if(traversal(current->right,count)) return true;
            count+=current->right->val;//回溯,撤销处理结果
        }
        return false;
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root==NULL) return false;
        return traversal(root,targetSum-root->val);
    }
};

3.leetcode 113.路径总和II

题目链接

这道题也是上一道题的一个补充。写完上一道题随便做了一下这道题。

这道题和上一道题的区别在于,上一道题是要找出二叉树中一条路径等于targetSum就可以了,就return true,否则return false。而这道题是要在这个二叉树中找出所有等于targetSum的路径,然后返回这个路径的所有的数字,所以这道题的返回值是一个二维数组。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
        vector<vector<int>> result;
        vector<int> path;
        //递归函数不要返回值,因为我们要遍历整个二叉树
        //这里的count跟上一道题的count是一个意思
        void traversal(TreeNode* current,int count){
            if(current->left==NULL&&current->right==NULL&&count==0){
                result.push_back(path);
                return;
            }
            if(current->left==NULL&&current->right==NULL&&count!=0) return;

            if(current->left){
                path.push_back(current->left->val);
                count-=current->left->val;
                traversal(current->left,count);
                count+=current->left->val;
                path.pop_back();
            }
            if(current->right){
                path.push_back(current->right->val);
                count-=current->right->val;
                traversal(current->right,count);
                count+=current->right->val;
                path.pop_back();
            }
            return;
        }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        if(root==NULL) return result;
        path.push_back(root->val);
        traversal(root,targetSum-root->val);
        return result;
    }
};

4.leetcode 106.从中序与后序遍历序列构造二叉树

题目链接

这道题算是比较难的二叉树的题目了。这道题如果单单分析的话,稍微动一点脑筋就可以分析出来,但是如果要用代码自己实现出来的话,还是比较难的。

说到一层一层切割,就应该想到了递归。

来看一下一共分几步:

第一步:如果数组大小为零的话,说明是空节点了。

第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点。

第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)第五步:切割后序数组,切成后序左数组和后序右数组。

第六步:递归处理左区间和右区间。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* traversal(vector<int>&inorder,vector<int>& postorder){
        if(postorder.size()==0) return NULL;
        
        //后序遍历的最后一个元素就是这个二叉树的根节点
        int rootValue=postorder[postorder.size()-1];
        TreeNode* root=new TreeNode(rootValue);

        //叶子节点
        if(postorder.size()==1) return root;

        //找到中序遍历的切割点
        int delimiterIndex;
        for(delimiterIndex=0;delimiterIndex<inorder.size();delimiterIndex++){
            if(inorder[delimiterIndex]==rootValue) break;
        }
        
        //切割中序数组
        //左闭右开区间
        vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
        vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());

        //postorder舍弃末尾元素
        postorder.resize(postorder.size()-1);

        //切割后序数组
        //还是左闭右开区间,注意这里是使用了左中序数组大小作为切割点
        vector<int> leftPostorder(postorder.begin(),postorder.begin()+leftInorder.size());
        vector<int> rightPostorder(postorder.begin()+leftInorder.size(),postorder.end());

        root->left=traversal(leftInorder,leftPostorder);
        root->right=traversal(rightInorder,rightPostorder);

        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size()==0||postorder.size()==0) return NULL;
        return traversal(inorder,postorder);
    }
};

5.leetcode 105.从前序与中序遍历序列构造二叉树

题目链接

这道题的思路跟上一道题的思路是一样的,只是有些地方稍微改动了一下。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* traversal(vector<int>& inorder,int inorderBegin,int inorderEnd,vector<int>& preorder,int preorderBegin,int preorderEnd){
        if(preorderBegin==preorderEnd) return NULL;

        int rootValue=preorder[preorderBegin];//注意这里是用preorderBegin,不能用0
        TreeNode* root=new TreeNode(rootValue);

        if(preorderEnd-preorderBegin==1) return root;

        int delimiterIndex;
        for(delimiterIndex=inorderBegin;delimiterIndex<inorderEnd;delimiterIndex++){
            if(inorder[delimiterIndex]==rootValue) break;
        }

        //切割中序数组
        //中序左区间,左闭右开
        int leftInorderBegin=inorderBegin;
        int leftInorderEnd=delimiterIndex;
        //中序右区间。左闭右开
        int rightInorderBegin=delimiterIndex+1;
        int rightInorderEnd=inorderEnd;

        //切割前序数组
        //前序左区间,左闭右开
        int leftPreorderBegin=preorderBegin+1;
        int leftPreorderEnd=preorderBegin+1+delimiterIndex-inorderBegin;//终止位置是起始位置加上中序左区间的大小size
        //前序右区间,左闭右开
        int rightPreorderBegin=preorderBegin+1+(delimiterIndex-inorderBegin);
        int rightPreorderEnd=preorderEnd;

        root->left=traversal(inorder,leftInorderBegin,leftInorderEnd,preorder,leftPreorderBegin,leftPreorderEnd);
        root->right=traversal(inorder,rightInorderBegin,rightInorderEnd,preorder,rightPreorderBegin,rightPreorderEnd);

        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(inorder.size()==0||preorder.size()==0) return NULL;
        //参数都坚持左闭右开原则
        return traversal(inorder,0,inorder.size(),preorder,0,preorder.size());
    }
};

温馨提示:看代码的时候一定要仔细看,不然的话容易看错代码,可能一个参数的改变,答案就错了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值