【Leetcode】-代码随想录算法训练营Day17|110.平衡二叉树,257. 二叉树的所有路径,404.左叶子之和

Leetcode题目-110. Balanced Binary Tree

链接: 110. Balanced Binary Tree

思路

本题中,高度平衡(height-balanced):一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。
高度是指当前节点到叶子结点的距离。所以要衡量当前节点是否平衡,要先获取到当前节点的左右子树的高度后,再进行比较。依照这个逻辑,可以想到使用的是后序遍历(查完左右后回到中)。后序遍历思路依然可以使用递归来解决。

  1. 确定递归函数:private int getHeight(TreeNode root)
    因为此题中,子树为平衡二叉树并不代表当前节点也是平衡二叉树,所以我们需要分别获取子树的高度,来比较,且当前节点的高度是子树的最大高度+1,所以我们的递归函数选取为获取当前节点高度。
  2. 递归终止条件:if (root==null) { return 0; }
    当遍历到空结点时,空节点的高度为0。
  3. 单次递归逻辑:分别计算当前节点的左右子树高度,进行比较后,如果高度差的绝对值超过1,则不是平衡二叉树(可以通过一个);如果不超过,当前节点的高度为左右子树最大值+1,然后返回上一层进行继续比较,直到回溯到根节点。

代码实现

class Solution {
    public boolean isBalanced(TreeNode root) {
        return getHeight(root) != -1;
    }

    private int getHeight(TreeNode root) {
        if (root == null) {
            return 0;
        }

        int leftHeight = getHeight(root.left);
        if (leftHeight == -1 ) {
            return -1;
        }
        int rightHeight = getHeight(root.right);
        if (rightHeight == -1) {
            return -1;
        }

        if (Math.abs(leftHeight - rightHeight) > 1) {
            return -1;
        }else {
            return Math.max(leftHeight, rightHeight) + 1;
        }
    }
}

总结

这里主要是要理解到后序遍历中,获取到左右子树的节点后,也将自己的高度回溯到上层中这一过程。同时注意二叉树的高度与深度的区别。(根节点的高度就是二叉树的深度)。

Leetcode题目-257. Binary Tree Paths

链接: 257. Binary Tree Paths

思路

这题需要记录所有根节点到叶子结点的路径。这里考虑前序遍历,因为要先获取到根节点后,再通过其指向它的左右子节点。但因为此题需要遍历所有的路径,所以这里涉及到回溯,完成一条路径后,需要回溯到上一节点,从而进行下一条路径的遍历。
使用递归解决:

  1. 确定递归函数:private void getPath(TreeNode root, String path, List<String> result)
  2. 递归终止条件:if (root == null) { result.add(path); }
    当递归到空节点时,完成一条路径的遍历,并添加到结果集中。
  3. 单层递归逻辑:将当前节点衔接到到path路径中,并接下去遍历当前节点的左右子节点,并注意递归后的回溯。

代码实现

class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        String path = "";
        List<String> result = new ArrayList<>();
        getPath(root, path, result);
        return result;
    }

    private void getPath(TreeNode root, String path, List<String> result) {
        path = path + root.val;

        if (root.left ==null && root.right == null) {
            result.add(path);
            return;
        }

        if (root.left != null) {
            getPath(root.left, path + "->", result);
        }
        
        if (root.right != null) {
            getPath(root.right, path + "->", result);
        }
    }
}

总结

注意隐藏的回溯逻辑,这里才传参的时候使用path + “->”,而非用path直接传参,所以隐式地隐藏了回溯。

Leetcode题目-404. Sum of Left Leaves

链接: 404. Sum of Left Leaves

思路

要找左叶子,首先需要是一个叶子结点(左右节点为空),同时它还是某个节点的左节点。这里使用后序遍历,因为获取到左右子节点后需要将获取到的结果累加到父节点,最后到根节点,就能获取到整棵树的结果总和。

  1. 确定递归函数:public int sumOfLeftLeaves(TreeNode root)
  2. 递归终止条件:if (root == null) return 0;
  3. 单层递归逻辑:判断当前节点的左右节点是否为叶子结点,如是,则累加到总和中。

代码实现

class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        if (root == null) {
            return 0;
        }

        if (root.left == null && root.right == null) {
            return 0;
        }

        int sum = 0;
        if (root.left != null && root.left.left == null && root.left.right == null) {
            sum += root.left.val;
        }

        return sum + sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right);
    }

}

总结

这里对遍历顺序的原理理解比较重要,因为要处理返回值,所以最后结果需要最后回收,采用后序来实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第二十二天的算法训练主要涵盖了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 ``` 以上就是第二十二天的算法训练的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值