C++刷题笔记(22)——leetcode404、513、112、113

题目1:404.左叶子之和

在这里插入图片描述
这一题的难点就在于:不能直接判断当前的节点是不是左叶子,比如示例中的7,需要根据他的根节点20来判断7是不是左叶子

因此需要通过节点的父节点来判断其左孩子是不是左叶子

如果某一节点的左节点不为空、左节点的左右节点为空,则该节点的左节点为左叶子。

解法一:递归法

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if (root == NULL) return 0;
        int leftValue = sumOfLeftLeaves(root->left);    // 左
        int rightValue = sumOfLeftLeaves(root->right);  // 右
        int midValue = 0;                               // 中                           
        if (root->left && !root->left->left && !root->left->right) { //当某个节点的左节点不为空但左节点的左右节点为空,那么这个节点的左节点为左叶子
            midValue = root->left->val;
        }
        int sum = midValue + leftValue + rightValue;
        return sum;
    }
};

简化后:

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if (root == NULL) return 0;
        return (root->left != NULL && root->left->left == NULL && root->left->right == NULL ? root->left->val : 0) + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
    }
};

解法二:迭代法

写法和之前的迭代法差不多,思路和递归法差不多

class Solution {
public:
    int sum0fLeftLeaves(TreeNode* root) {
        stack<TreeNode*>st;
        if (root == NULL) return 0;
        st.push(root);
        int result = 0;
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            if (node->left != NULL && node->left->left != NULL && node->left->right == NULL) {
                result += node->left->val;
            }
            if (node->right) st.push(node->right);
            if (node->left) st.push(node->left);
        }
        return result;
    }
};

题目2:513.找树左下角的值

在这里插入图片描述

解法一:迭代法

最底层的最左边节点的值,可以用层序遍历

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*>que;
        if (root != NULL) que.push(root);
        int result = 0;
        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;
    }
};

解法二:递归法

最后一行最左边的值

那么可以定义一个深度最大值,每次更新最大深度;
最左边的值,可以先遍历左子树,再遍历右子树

class Solution {
public:
    int maxdepth = INT_MIN;                               //全局变量,记录最大深度
    int maxdepthvalue;                                    //全局变量,记录最大深度最左节点的数值
    void traversal(TreeNode* root, int depth) {           //传入根节点、depth记录当前深度
        if (root->left == NULL && root->right == NULL) {  //遇到叶子节点
            if (depth > maxdepth) {                       //如果当前遍历的深度大于最大深度
                maxdepth = depth;                         //更新最大深度
                maxdepthvalue = root->val;                //更新最大深度最左节点的数值
            }
            return;
        }
        if (root->left) {                                 //左
            depth++;                                      //深度加一
            traversal(root->left, depth);
            depth--;                                      //回溯,深度减一
        }
        if (root->right) {
            depth++;
            traversal(root->right, depth);
            depth--;
        }
        return;
    }
    int findBottemLeftValue(TreeNode* root) {
        traversal(root,0);
        return maxdepthvalue;
    }
};

根据评论区大佬进行了简单的化简:

class Solution {
public:
    int maxdepth = -1; 
    int maxleftvalue;
    void traversal(TreeNode* root, int depth) {
        if (root== NULL)   return;
        if (depth > maxdepth) {
            maxleftvalue = root->val;
            maxdepth++;
        }
        traversal(root->left, depth + 1);
        traversal(root->right, depth + 1);
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 0);
        return maxleftvalue;
    }
};

题目3:112.路径之和

在这里插入图片描述
在这里插入图片描述
如果需要遍历整棵树,递归函数就不能有返回值。如果需要遍历某一条固定路线,递归函数就一定要有返回值。

这里关于递归函数返回值,有一个说法:

如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。
如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。
如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。

解法一:递归法

class Solution {
public:
    bool traversal(TreeNode* node, int count) {     //传入根节点,count计算二叉树一边之和、通过递减让count减去路径上节点的值
        if (node->left == NULL && node->right == NULL && count == 0) return true;  //遇到叶子节点且计数为0,则找到了符合目标和的边
        if (node->left == NULL && node->right == NULL) return false; //遇到叶子节点但count不为0,则没有找到符合条件的边
        if (node->left) {                   //左(空节点不遍历)
            //count -= node->left->val;
            //if (traversal(node->left, count)) return true;  //递归
            //count += node->left->val;     //回溯,撤销处理结果
            if (traversal(node->left, count - node->left->val)) return true;  //把count - cur->left->val 直接作为参数传进去,函数结束,count的数值没有改变。
        }
        if (node->right) {
            //count -= node->right->val;
            //if (traversal(node->right, count)) return true;
            //count += node->left->val;
            if (traversal(node->right, count - node->right->val)) return true;
        }
        return false;
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL) return false;
        return  traversal(root, targetSum - root->val);   //先减去头结点的值
    }
};

代码精简后:

class solution {
public:
    bool haspathsum(treenode* root, int sum) {
        if (root == null) return false;
        if (!root->left && !root->right && sum == root->val) {
            return true;
        }
        return haspathsum(root->left, sum - root->val) || haspathsum(root->right, sum - root->val);
    }
};

题目4:113.路径之和Ⅱ

在这里插入图片描述
解题思路和112差不多

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void traversal(TreeNode* node, int count) {        //遍历整棵树,递归函数不需要返回值
        if (node->left == NULL && node->right == NULL && count == 0) {
            result.push_back(path);
            return;
        }
        if (node->left && node->right) return;
        if (node->left) {   //这里隐藏了判空
            path.push_back(node->left->val);
            count -= node->left->val;
            traversal(node->left, count);    // 递归
            count += node->left->val;        // 回溯
            path.pop_back();                 // 回溯
        }
        if (node->right) {
            path.push_back(node->right->val);
            count -= node->right->val;
            traversal(node->right, count);
            count += node->right->val;       
            path.pop_back();                
        }
        return;
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        if (root == nullptr) return result;
        path.push_back(root->val);
        traversal(root, targetSum - root->val);
        return result;
    }
};

精简后的代码:

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void traversal(TreeNode* node, int count) {
        if (node == nullptr) return;
        path.push_back(node->val);
        count -= node->val;
        if (node->left == nullptr && node->right == nullptr && count == 0) {
            result.push_back(path);
        }
        traversal(node->left, count);
        traversal(node->right, count);
        path.pop_back();
    }

    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        traversal(root, targetSum);
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值