力扣算法打卡7

671. 二叉树中第二小的节点

给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个。
更正式地说,root.val = min(root.left.val, root.right.val) 总成立。
给出这样的一个二叉树,你需要输出所有节点中的第二小的值。如果第二小的值不存在的话,输出 -1 。
示例 1
输入:root = [2,2,5,null,null,5,7]
输出:5
解释:最小的值是 2 ,第二小的值是 5 。
示例 2
输入:root = [2,2,2]
输出:-1
解释:最小的值是 2, 但是不存在第二小的值。
提示
树中节点数目在范围 [1, 25] 内
1 <= Node.val <= 231 - 1
对于树中每个节点 root.val == min(root.left.val, root.right.val)

解题思路:根节点永远是最小的那个

  1. 利用递归遍历二叉树,遇到叶子节点则结束递归
  2. 当前节点值若大于根节点值,并且小于当前第二小值,则更新第二小的值
  3. 由于第二小的值初始化为-1,所以第二步多一步判断,即(第二小值 == -1)
  4. 返回第二小值

代码如下

int min, min1 = -1;
public int findSecondMinimumValue(TreeNode root) {
    if (root == null) {
        return -1;
    }
    min = root.val;
    recursion(root);
    return min1;
}

public void recursion(TreeNode root) {
    if (root != null) {
        if (root.val > min && (root.val <= min1 || min1 < 0)) {
            min1 = root.val;
        }
        recursion(root.left);
        recursion(root.right);
    }
}

1695. 删除子数组的最大得分

给你一个正整数数组 nums ,请你从中删除一个含有 若干不同元素 的子数组。删除子数组的 得分 就是子数组各元素之 和 。
返回 只删除一个 子数组可获得的 最大得分 。
如果数组 b 是数组 a 的一个连续子序列,即如果它等于 a[l],a[l+1],...,a[r] ,那么它就是 a 的一个子数组。
示例 1
输入:nums = [4,2,4,5,6]
输出:17
解释:最优子数组是 [2,4,5,6]
示例 2
输入:nums = [5,2,1,2,5,2,1,2,5]
输出:8
解释:最优子数组是 [5,2,1] 或 [1,2,5]
提示
1 <= nums.length <= 100000
1 <= nums[i] <= 10000

解题思路:滑动窗口不断右移,保证窗口内的元素唯一,同时更新最大得分

  1. 初始化滑动窗口左边界为数组下标0,右边界为数组下标1,最大得分为左边第一个元素值,同时定义一个临时最大值,初始为左边第一个元素值,用于和最大得分比较,大于最大得分则更新最大得分
  2. 由于已知元素值最大不超过10000,因此可以利用一个大小10001的数组来存储元素是否存在于滑动窗口内,提升效率
  3. 右边界从1开始不断右移,利用boolean数组判断右边元素是否已经存在于窗口内,若不存在,则将boolean数组对应下标(右边元素值)置为true表示该元素已存在,并更新临时最大值为临时最大值;若存在,则左边界需要不断左移至存在元素的位置,每次左移都要更新临时最大值=临时最大值-左移的值
  4. 每次右移一位,都需要用临时最大值和当前最大得分来比较,得出最大值,并更新最大得分
  5. 当右边界移至数组尾部时,结束移动,返回最大得分即可

代码如下

public int maximumUniqueSubarray(int[] nums) {
    int max = nums[0];
    int max1 = max;
    int left = 0, right = 1;
    boolean[] booleans = new boolean[10001];
    booleans[max] = true;
    while (right < nums.length) {
        int rightNum = nums[right];
        if (!booleans[rightNum]) {
            max1 += rightNum;
            booleans[rightNum] = true;
        } else {
            booleans[rightNum] = false;
            while (booleans[nums[left]]) {
                max1 -= nums[left];
                booleans[nums[left]] = false;
                left++;
            }
            booleans[rightNum] = true;
            ++left;
        }
        max = Math.max(max, max1);
        ++right;
    }
    return max;
}

面试题 10.11. 峰与谷

在一个整数数组中,“峰”是大于或等于相邻整数的元素,相应地,“谷”是小于或等于相邻整数的元素。例如,在数组{5, 8, 4, 2, 3, 4, 6}中,{8, 6}是峰, {5, 2}是谷。现在给定一个整数数组,将该数组按峰与谷的交替顺序排序。
示例:
输入: [5, 3, 1, 2, 3]
输出: [5, 1, 3, 2, 3]
提示
nums.length <= 10000

解题思路

  1. 利用boolean来标志当前需要峰->谷还是谷->峰,初始化为true表示峰->谷
  2. 从第二个元素开始遍历数组,每次与前一个元素作比较
  3. 若前一个元素小于当前元素,且标志为峰->谷,则需要对这两个元素进行交换
  4. 每次循环都要对标志取反,表示峰谷顺序变换
  5. 遍历完后,即完成了峰谷交替

代码如下

public void wiggleSort(int[] nums) {
    boolean flag = true;
    for (int i=1; i<nums.length; i++) {
        if (nums[i-1] < nums[i] == flag) {
            int temp = nums[i-1];
            nums[i-1] = nums[i];
            nums[i] = temp;
        }
        flag = !flag;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容