代码随想录Day33|贪心算法|122.买卖股票的最佳时机II、55. 跳跃游戏、45.跳跃游戏II、1005.K次取反后最大化的数组和


代码随想录开源LeetCode题单:代码随想录


1.LeetCode122

LeetCode122.买卖股票的最佳时机II

1.1 思路

由于没有限制交易次数,可以尽可能利用价格上涨的区间获利。
如果某天价格比前一天高,则可以视为当天卖出前一天买入的利润。多次交易的总利润等价于每天的上涨差值之和。

  • 算法核心:
    • 遍历价格数组:如果 prices[i] > prices[i-1],则将差值 prices[i] - prices[i-1] 累加到总利润中。
    • 通过这样的贪心策略,不需要关心具体的买卖时机,保证所有上涨的利润都被捕获。
  • 贪心策略有效性:
    假设价格从 prices[i-1] 到 prices[i] 是递增的:即 prices[i] > prices[i-1]。贪心策略通过每天的差值累加,等效于在最低点买入,最高点卖出。
  • 终止条件:
    遍历完整个数组后,返回累计利润。

1.2 代码

class Solution {
    public int maxProfit(int[] prices) {
        int result = 0;
        for (int i = 1; i < prices.length; i++) {
            result += Math.max(prices[i] - prices[i - 1], 0);
        }
        return result;
    }
}

2.LeetCode55

LeetCode55. 跳跃游戏

2.1思路

  • 核心思路:

    • 维护一个变量 maxPos,表示当前可以跳跃到的最远位置。
    • 遍历数组时,如果当前位置 i 超过了 maxPos,说明无法到达当前位置,因此返回 false。
    • 遍历过程中,更新 maxPos 为 max(maxPos, i + nums[i])。
  • 贪心策略:

    • 每一步都尽可能跳得更远,从而保证最远可达的位置始终在当前范围内的最大值。
    • 如果遍历完成后,始终没有返回 false,说明可以到达最后一个位置,返回 true。
  • 终止条件:

    • 如果当前索引 i > maxPos,说明当前位置不可达
    • 如果遍历完成,返回 true,表示可以到达最后位置

2.2 代码

class Solution {
    public boolean canJump(int[] nums) {
        if (nums.length == 1) {
            return true;
        }
        //覆盖范围, 初始覆盖范围应该是0,因为下面的迭代是从下标0开始的
        int coverRange = 0;
        //在覆盖范围内更新最大的覆盖范围
        for (int i = 0; i <= coverRange; i++) {
            coverRange = Math.max(coverRange, i + nums[i]);
            if (coverRange >= nums.length - 1) {
                return true;
            }
        }
        return false;
    }
}

3.LeetCode45

LeetCode45.跳跃游戏II

3.1 思路

从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最少步数!需要统计两个覆盖范围,当前这一步的最大覆盖和下一步最大覆盖。
如果移动下标达到了当前这一步的最大覆盖最远距离了,还没有到终点的话,那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点。

3.2 代码

class Solution {
    public int jump(int[] nums) {
        int result = 0;
        // 当前覆盖的最远距离下标
        int end = 0;
        // 下一步覆盖的最远距离下标
        int temp = 0;
        for (int i = 0; i <= end && end < nums.length - 1; ++i) {
            temp = Math.max(temp, i + nums[i]);
            // 可达位置的改变次数就是跳跃次数
            if (i == end) {
                end = temp;
                result++;
            }
        }
        return result;
    }
}

4.LeetCode1005

LeetCode1005.K次取反后最大化的数组和

4.1 思路

  • 贪心算法:
    • 局部最优:只找数值最小的正整数进行反转,当前数值和可以达到最大(例如正整数数组{5, 3, 1},反转1 得到-1 比 反转5得到的-5 大多了。
    • 全局最优:整个数组和达到最大。
  • 本题的解题步骤:
    • 将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
    • 从前向后遍历,遇到负数将其变为正数,同时k自减
    • 如果k还大于0,那么反复转变数值最小的元素,将k用完
    • 求和

4.2 代码

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
    	// 将数组按照绝对值大小从大到小排序(注意要按照绝对值的大小)
	nums = IntStream.of(nums)
		     .boxed()
		     .sorted((o1, o2) -> Math.abs(o2) - Math.abs(o1))
		     .mapToInt(Integer::intValue).toArray();
	int len = nums.length;	    
	for (int i = 0; i < len; i++) {
	    //从前向后遍历,遇到负数将其变为正数,同时k--
	    if (nums[i] < 0 && k > 0) {
	    	nums[i] = -nums[i];
	    	k--;
	    }
	}
	// 如果k还大于0,那么反复转变数值最小的元素,将k用完
	if (k % 2 == 1) nums[len - 1] = -nums[len - 1];
	return Arrays.stream(nums).sum();

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值