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

1. LeetCode 530.二叉搜索树的最小绝对差

题目链接:https://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/
文章链接:https://programmercarl.com/0530.二叉搜索树的最小绝对差.html
视频链接:https://www.bilibili.com/video/BV1DD4y11779

在这里插入图片描述

思路:
使用中序遍历。因为二叉搜索树中序遍历是单调递增的,通过前后两个节点的差值与最小值进行比较,找出最终最小值。

解法:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    TreeNode pre = null;
    int min = Integer.MAX_VALUE;
    // 中序遍历递归法
    // public int getMinimumDifference(TreeNode root) {
    //     if(root==null || (root.left==null && root.right==null)) {
    //         return 0;
    //     }
    //     find(root);
    //     return min;
    // }

    // // 中序遍历
    // public void find(TreeNode root) {
    //     if (root == null) return;

    //     // 左
    //     find(root.left);

    //     // 中
    //     if (pre!=null) {
    //         int curInter = root.val - pre.val;
    //         if (curInter < min) {
    //             min = curInter;
    //         }
    //     }
    //     pre = root;

    //     // 右
    //     find(root.right);
    // }

    public int getMinimumDifference(TreeNode root) {
        find(root);
        return min;
    }

    // 中序遍历迭代法
    public void find(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        if (root == null || (root.left==null && root.right==null)) {
            min = 0;
            return;
        }

        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            if (cur != null) {
                stack.push(cur);
                // 左
                cur = cur.left;
            } else {
                // 中
                cur = stack.pop();// 当前节点
                if (pre != null) {
                    if (cur.val-pre.val<min) {
                        min = cur.val-pre.val;
                    }
                }
                pre = cur;
                // 右
                cur = cur.right;
            }
        }
    }
}

2. LeetCode 501.二叉搜索树中的众数

题目链接:https://leetcode.cn/problems/find-mode-in-binary-search-tree/description/
文章链接:https://programmercarl.com/0501.二叉搜索树中的众数.html
视频链接:https://www.bilibili.com/video/BV1fD4y117gp

在这里插入图片描述

思路:
使用中序遍历。
首先将当前节点与前一节点进行比较,若相等,则当前节点的计数加1;否则当前节点的计数等于1。
然后比较当前节点的计数与最大计数,若大于,则清空集合,并传入当前节点的值;若相等,则传入当前节点的值;若小于,则不传入集合。

解法:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    
    int count = 1;
    int max = 1;
    TreeNode pre = null;
    List<Integer> modes = new ArrayList<>();

    public int[] findMode(TreeNode root) {
        find(root);
        // 将众数列表转换为数组
        return modes.stream().mapToInt(Integer::intValue).toArray();
    }

    private void find(TreeNode cur) {
        if (cur == null) {
            return;
        }
        // 左
        find(cur.left);
        // 中
        if (pre != null) {
            if (pre.val == cur.val) {
                count++;
            } else {
                count = 1;
            }
        }
        if (count > max) {
            max = count;
            modes.clear();
            modes.add(cur.val);
        } else if (count == max) {
            modes.add(cur.val);
        }
        pre = cur;
        // 右
        find(cur.right);
    }

}

3.LeetCode 236. 二叉树的最近公共祖先

题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/description/
文章链接:https://programmercarl.com/0236.二叉树的最近公共祖先.html
视频链接:https://www.bilibili.com/video/BV1jd4y1B7E2

在这里插入图片描述

思路:使用后序遍历从底往上递归方式。
解题关键是,只有左右节点返回都不是空时,当前节点才是公共祖先。
若有一个左或右节点为空,说明当前节点不是公共祖先,公共祖先在上面的层上,将不为空的节点继续返回,表示上面的递归中,某个节点的某个子树中含有某一个目标节点,只需找到左右子树都含有目标节点的节点,即公共祖先。

归纳如下三点:
1️⃣求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从底向上的遍历方式。
2️⃣在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。
3️⃣要理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。

解法:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) return null;

        // 左
        TreeNode left = lowestCommonAncestor(root.left,p,q);
        // 右
        TreeNode right = lowestCommonAncestor(root.right,p,q);

        // 中
        if (root == p || root == q) {
            return root;
        }

        if (left != null && right == null) {
            return left;
        } else if (left == null && right != null) {
            return right;
        } else if (left == null && right == null) {
            return null;
        } else {
            return root;
        }
    }
}
  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值