LeetCode 45、1005

119 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情

本文包括下面几题:

  1. 跳跃游戏II,数组中每个位置代表可跳跃的最大长度,要求找到最少跳到最后一个位置的次数。
  2. 给定一个数组nums和一个整数k,选择某个下标i并将nums[i]替换为-nums[i],整个过程恰好k次。

解题思路

LeetCode 45 跳跃游戏II

本题和之前跳跃游戏的思路一致,都是使用最大跳跃范围来解答,但什么时候步数增加是本题需要考虑的问题。首先考虑每步的最大范围,需要注意的是,每步的最大范围并不是我们已经走到的位置,只是可到达的位置,那中间应该走几步我们是不知道的。

想象一下,如果数组为[2,3,1,1,4],那第一步的最大范围为走到数组中第一个1,那究竟是先走到3再走到1是不得而知的,但可以确定的是,如果我们顺序遍历到了第一个1,那第一步必然是走了的,此时就可以步数加一,既然第一步走完了,那么我们可以根据更新最大范围,找到我们肯定走到的第二步。可得代码如下:

public int jump(int[] nums) {
    if(nums.length==1) return 0;
    int count = 0;
    int maxRange = 0;
    int curRange = 0;
    for(int i=0;i<nums.length-1;i++){
        maxRange = Math.max(maxRange, i+nums[i]);
        if(i==curRange){
            curRange = maxRange;
            count++;
        }
        if(curRange>=nums.length-1) return count;
    }
    return count;
}

叙述的较为抽象,可结合代码来看。

LeetCode 1005 k次取反后最大化数组和

本题的思路很简单,我们只需要将数组按照绝对值从大到小排序,每次将大的负数反转,如果最终k还大于0,那只需要对最小的一个数进行来回翻转即可,最终就可以得到结果。

根据上述思路可得代码如下:

public int largestSumAfterKNegations(int[] nums, int k) {
    int res = 0;
    nums = IntStream.of(nums)
        .boxed()
        .sorted((o1, o2) -> Math.abs(o2) - Math.abs(o1))
        .mapToInt(Integer::intValue).toArray();
    for(int i=0;i<nums.length;i++){
        if(nums[i]<0&&k>0){
            nums[i] = -nums[i];
            k--;
        }
    }
    if(k!=0){
        nums[nums.length-1] = k%2==1?-nums[nums.length-1]:nums[nums.length-1];
    }
    for (int num : nums) {
        res+=num;
    }

    return res;
}