代码随想录算法训练营第16天|530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

LeetCode530

2025-02-15 18:33:33 星期六

题目描述:力扣530
文档讲解:代码随想录(programmercarl)530.二叉搜索树的最小绝对差
视频讲解:《代码随想录》算法视频公开课:二叉搜索树中,需要掌握如何双指针遍历!| LeetCode:530.二叉搜索树的最小绝对差

代码随想录视频内容简记

本题和98验证二叉搜索树的做法有着异曲同工之妙,都是用双指针的思想来完成会好做。仍旧是采用中序遍历。

梳理

  1. 确定递归函数的参数和返回值

  2. 确定递归的终止条件

  3. 确定单层递归的逻辑

大致代码内容

  1. 首先定义一个空结点TreeNode* pre = NULL,定义一个void traversal(TreeNode* cur)

  2. 确定递归的终止条件,if (cur == NULL) return;

  3. 确定单层递归的逻辑

    1. 向左遍历,traversal(cur->left)

    2. 对中间进行处理,if (pre != NULL) result = min(result, abs(pre->val, cur->val)),还有关键的一步就是pre = cur

    3. 向右遍历,traversal(cur->right)

    返回最后的根结点

LeetCode测试

这个注意,就是result要定义在函数体的外部,因为这个最后要最为返回值,所以必须是int函数可以返回的值

至于这个类内部的共有和私有倒是不打紧,就是书写的习惯

点击查看代码
class Solution {
private:
    TreeNode* pre = NULL;
    int result = INT_MAX;
    void traversal(TreeNode* cur) {
        if (cur == NULL) return;
        traversal(cur->left);
        if (pre != NULL) result = min(result, cur->val - pre->val);
        pre = cur;
        traversal(cur->right);
    }
    
public:
    int getMinimumDifference(TreeNode* root) {
        traversal(root);
        return result;
    }
};

LeetCode501

题目描述:力扣501
文档讲解:代码随想录(programmercarl)501.二叉搜索树中的众数
视频讲解:《代码随想录》算法视频公开课:不仅双指针,还有代码技巧可以惊艳到你! | LeetCode:501.二叉搜索树中的众数

代码随想录视频内容简记

这个题的初步想法就是遍历一边二叉树,得到这颗二叉树元素的最大频率maxCount,之后再遍历一边二叉树,凡是出现频率等于maxCount的元素就对这个元素放入result数组中。这里为什么要遍历两遍,主要是因为要对count = maxCount的元素进行再一次的遍历来确认,因为众数可能相等,也就是不止一个。

k哥给出的优化是减少两次遍历为一次遍历,依旧是采用双指针的思想,在第一次遍历的时候用了一个技巧。

另外就是针对于二叉搜索树,利用其本身自带的顺序,依旧是采用中序遍历

梳理

  1. 确定递归函数的参数和返回值

  2. 确定递归的终止条件

  3. 确定单层递归的逻辑

大致代码内容

  1. 定义一个void traversal(TreeNode* cur)

  2. if (cur == NULL) return;

  3. 确定单层递归的逻辑。

    1. 首先是左,traversal(cur->left)

    2. 再是中,首先是if (pre == NULL) count = 1,初始化pre的频率为1,else if (pre->val == cur->val) count++; else count = 1,如果二者不相等,再重新赋值为1,重新开始记。最后这里记得更新pre所指的位置,第一遍的时候就是忘了这个了,pre = cur。接着,就到了上文k哥说到的技巧了。如果if (count == maxCount) result.push_back(cur->val),这里先不用着急,真正的神来之笔在下面。if (count > maxCount) result.clear(); maxCount = count;result.push_back(cur->val),也就是说一旦有更大的数组,就把之前旧的清空了,然后再把这个更大的添加进去,(虽然感觉这种行为不太好,有点渣渣的,但k哥说了确实可以提高运行效率🤔)

    3. 最后是右,travesal(cur->right)

  4. return result;

LeetCode测试

点击查看代码
class Solution {
private:
    int count = 0, maxCount = 0;
    vector<int> result;
    TreeNode* pre = NULL;
    void traversal(TreeNode* cur) {
        if (cur == NULL) return;
        // 左
        traversal(cur->left);
        // 中
        if (pre == NULL) count = 1;
        else if (pre->val == cur->val) count++;
        else count = 1;
        // 记得更新pre指针
        pre = cur;
        if (count == maxCount) result.push_back(cur->val);
        if (count > maxCount) {
            result.clear();
            maxCount = count;
            result.push_back(cur->val);
        }
        // 右
        traversal(cur->right);
    }

public:
    vector<int> findMode(TreeNode* root) {
        traversal(root);
        return result;
    }
};

LeetCode236

题目描述:力扣236
文档讲解:代码随想录(programmercarl)236. 二叉树的最近公共祖先
视频讲解:《代码随想录》算法视频公开课:自底向上查找,有点难度! | LeetCode:236. 二叉树的最近公共祖先

代码随想录视频内容简记

这道题是用后序遍历,让对结点的判断返回值自底向上返回,从而求公共祖先

梳理

  1. 确定函数的参数和返回值,TreeNode* traversal(TreeNode* root, TreeNode* p, TreeNode* q)

  2. 确定递归函数的终止条件,if (root == NULL) return NULL; if (root == p || root == q) return root;

  3. 确定单层递归的逻辑。

    1. 首先是左,root->left = traversal(root->left, p, q);

    2. 然后是右,root->right = traversal(root->right, p, q);

    3. 最后是中,这里需要对左和右的条件进行处理,进行条件判断,if (root->left == NULL && root->right == NULL) return NULLif (root->left == NULL && root->right != NULL) return right; if (root->left != NULL && root->right == NULL) return left; 最后一个,if (root->left != NULL && root->right != NULL) return root;

LeetCode测试

感觉这里面的回溯过程认识不深刻,博客园这个缩进真是难搞(((φ(◎ロ◎;)φ)))

点击查看代码
class Solution {
public:
	TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
		if (root == NULL) return NULL;
		if (root == p || root == q) return root;
		// 左
		root->left = lowestCommonAncestor(root->left, p, q);
		// 右
		root->right = lowestCommonAncestor(root->right, p, q);
		// 中
		if (root->left == NULL && root->right == NULL) return NULL;
		if (root->left != NULL && root->right != NULL) return root;
		// 如果有回溯我感觉是下面这两条体现的
		if (root->left == NULL && root->right != NULL) return root->right;
		if (root->left != NULL && root->right == NULL) return root->left;

		return root;
    }
};
posted on   bnbncch  阅读(1194)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示