力扣二分查找练习题(长度最小的子数组、完全二叉树的节点个数)

123 阅读3分钟

长度最小的子数组

来源:力扣(LeetCode) 链接:leetcode.cn/problems/mi…

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]

输出:2

解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]

输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]

输出:0

提示:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105

代码

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        int minLength = Integer.MAX_VALUE;
        int left = 0;
        int sum = 0;
        
        for (int right = 0; right < n; right++) {
            sum += nums[right];
            
            while (sum >= target) {
                minLength = Math.min(minLength, right - left + 1);
                sum -= nums[left];
                left++;
            }
        }
        
        return minLength != Integer.MAX_VALUE ? minLength : 0;
    }
}

思路分析

  1. 初始化左指针left为0,右指针right为0,子数组的和sum为0,最小长度minLength为一个较大的初始值(这里使用Integer.MAX_VALUE)。

  2. 在循环中,执行以下操作:

    • 将右指针right向右移动一位,并将当前位置的元素加入到sum中。
    • sum大于或等于目标值target,表示当前子数组的和满足条件,更新最小长度minLength为当前子数组的长度。
    • 进入内层循环,当sum大于或等于目标值target时,不断将左指针left向右移动一位,并将相应位置的元素从sum中减去,直到sum小于目标值target
    • 每次移动左指针left时,更新最小长度minLength为当前子数组的长度。
  3. 当循环结束时,返回最小长度minLength。如果minLength仍然为初始值,则表示没有满足条件的子数组,返回0。

完全二叉树的节点个数

来源:力扣(LeetCode) 链接:leetcode.cn/problems/co…

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例 1:

图片.png

输入:root = [1,2,3,4,5,6]

输出:6

示例 2:

输入:root = []

输出:0

示例 3:

输入:root = [1]

输出:1

提示:

  • 树中节点的数目范围是[0, 5 * 104]
  • 0 <= Node.val <= 5 * 104
  • 题目数据保证输入的树是 完全二叉树

代码

class Solution {
    public int countNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        int leftHeight = getLeftHeight(root);
        int rightHeight = getRightHeight(root);
        
        if (leftHeight == rightHeight) {
            return (1 << leftHeight) - 1;
        } else {
            return countNodes(root.left) + countNodes(root.right) + 1;
        }
    }
    
    private int getLeftHeight(TreeNode root) {
        int height = 0;
        while (root != null) {
            height++;
            root = root.left;
        }
        return height;
    }
    
    private int getRightHeight(TreeNode root) {
        int height = 0;
        while (root != null) {
            height++;
            root = root.right;
        }
        return height;
    }
}

思路分析

  1. 首先判断根节点是否为空,如果为空,则返回节点个数为0。
  2. 计算左子树的高度,可以通过不断向左遍历子节点,直到节点为空,记录遍历的次数即为左子树的高度。
  3. 计算右子树的高度,可以通过不断向右遍历子节点,直到节点为空,记录遍历的次数即为右子树的高度。
  4. 如果左子树的高度等于右子树的高度,说明左子树是一棵满二叉树,节点个数为(2^左子树高度) - 1。然后递归计算右子树的节点个数。
  5. 如果左子树的高度不等于右子树的高度,说明右子树是一棵满二叉树,节点个数为(2^右子树高度) - 1。然后递归计算左子树的节点个数。
  6. 最后将左子树、右子树以及根节点的节点个数相加,并返回结果。