代码随想录打卡Day21| 二叉树part07

心得:

注意用for遍历数组元素中相邻两个元素的差时,i从1开始就可以一直到size,从0开始则要让i<size - 1.

二叉树没法从下往上遍历,但是可以用回溯来从下往上处理。

递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)
  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先 (opens new window)中介绍)
  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(112.路径总和)


第一题、二叉搜索树中的最小绝对差 LeetCode530 https://leetcode.cn/problems/minimum-absolute-difference-in-bst/

可以和前一天的最后一题类似,放入数组中然后找出相邻两个数的最小差。

注意用for遍历数组元素中相邻两个元素的差时,i从1开始就可以一直到size,从0开始则要让i<size - 1.

class Solution {
public:
    vector<int> vec;
    void traversal(TreeNode* node){
        if(node == NULL) return;
        traversal(node->left);
        vec.push_back(node->val);
        traversal(node->right);
    }

    int getMinimumDifference(TreeNode* root) {
        int res = INT_MAX;
        vec.clear();
        traversal(root);
        if (vec.size() < 2) return 0;
        for(int i = 0; i < vec.size()-1; i++){
            int dif = vec[i + 1] - vec[i];
            res = min(res, dif);
        }
        // for(int i = 1; i < vec.size(); i++){
        //     int dif = vec[i] - vec[i - 1];
        //     res = min(res, dif);
        // }
        return res;
    }
};

 当然也可以不用额外的数组,直接遍历节点然后直接计算。使用双指针法,一个pre指针指向前一个节点。

class Solution {
public:
    int res = INT_MAX;
    TreeNode* pre = NULL;   
    
    void traversal(TreeNode* cur){
        if(cur == NULL) return;

        traversal(cur->left);
        if(pre != NULL){
            res = min(res, cur->val - pre->val);
        }
        pre = cur;//记录前一个节点
        traversal(cur->right);
    }

    int getMinimumDifference(TreeNode* root) {
        traversal(root);
        return res;
    }
};


第二题,二叉搜索树的众数 LeetCode501 https://leetcode.cn/problems/find-mode-in-binary-search-tree/submissions/

思路上是可以用双指针法将整个二叉树遍历一边,再把结果集遍历一遍找出最高频率的数。但通过使用count和maxcount的技巧,可以不用遍历两边。

如果 频率count 等于 maxCount(最大频率),当然要把这个元素加入到结果集中(以下代码为result数组),代码如下:

if (count == maxCount) { // 如果和最大值相同,放进result中
    result.push_back(cur->val);
}

为什么result怎么能轻易就把元素放进去了呢?万一,这个maxCount此时还不是真正最大频率呢。

所以下面要做如下操作:

频率count 大于 maxCount的时候,不仅要更新maxCount,而且要清空结果集(以下代码为result数组),因为结果集之前的元素都失效了。

if (count > maxCount) { // 如果计数大于最大值
    maxCount = count;   // 更新最大频率
    result.clear();     // 很关键的一步,不要忘记清空result,之前result里的元素都失效了
    result.push_back(cur->val);
}

class Solution {
public:
    int maxCount = 0;
    int count = 0;
    TreeNode* pre = NULL;
    vector<int> res;

    
    void searchBST(TreeNode* cur){
        if(cur == NULL) return;
        searchBST(cur->left);

        if(pre == NULL){//第一个节点
            count = 1;
        } 
        else if(pre->val == cur->val){//值相同的节点
            count++;
        } 
        else{//值不相同的节点
            count = 1;
        } 
        pre = cur;
        //如果和maxcount相同,则放入结果集
        if(count == maxCount) res.push_back(cur->val);
        
        if(count > maxCount){//如果大于最大频率
            maxCount = count;//更新最大频率吧
            res.clear();//不要忘记把之前的result清空
            res.push_back(cur->val);
        }

        searchBST(cur->right);
        return;
    }
    vector<int> findMode(TreeNode* root) {
        count = 0;
        maxCount = 0;
        TreeNode* pre = NULL;
        res.clear();
        searchBST(root);
        return res;
    }
};

 



第三题、二叉树的最近公共祖先 LeetCode 236https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/

递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)
  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先 (opens new window)中介绍)
  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(112.路径总和)

 就这道题而言,要对left和right的递归值进行处理,所以递归函数就需要按返回值。

left = 递归函数(root->left);  // 左
right = 递归函数(root->right); // 右
left与right的逻辑处理;         // 中 

 

那么先用left和right接住左子树和右子树的返回值,代码如下:

TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);

如果left 和 right都不为空,说明此时root就是最近公共节点。这个比较好理解

如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之依然

为什么呢? 

 如果left 和 right都不为空,说明此时root就是最近公共节点。左右分别和一同为空在下面进行处理。

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == p || root == q || root == NULL) return root;
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        
        //如果left 和 right都不为空,说明此时root就是最近公共节点。
        if (left != NULL && right != NULL) return root;
        
        if(left == NULL && right == NULL){
            return NULL;
        }
        else if(left != NULL && right == NULL){
            return left;
        }
        else{
            return right;
        }
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值