代码随想录第二十八天| 122.买卖股票的最佳时机 II 55. 跳跃游戏 45.跳跃游戏II 1005.K次取反后最大化的数组和

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

题目描述

给定一个数组 prices,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:

  • 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

解题思路

  1. 方法一:模拟买卖过程

    • 使用变量 front 记录买入价格,used 标记是否已经买入股票。
    • 遍历数组,计算每天的价格差 pre = prices[i+1] - prices[i]
      • 如果 pre > 0 且未买入(used == false),记录买入价格 front 并标记已买入。
      • 如果 pre < 0 且已买入(used == true),卖出当前股票,将利润加入总利润 count,并重置标记。
    • 遍历结束后,若股票仍未卖出(used == true),则在最后一天卖出并计算利润。
    • 时间复杂度:O(n),空间复杂度:O(1)。
  2. 方法二:贪心算法

    • 只要价格上涨,即 pre = prices[i] - prices[i-1] > 0,直接将差值加入总利润 count
    • 不需要记录具体的买卖操作,只需累加所有的上涨区间。
    • 时间复杂度:O(n),空间复杂度:O(1)。

Java代码

class Solution {
    public int maxProfit(int[] prices) {
        int count = 0;
		int front = 0;
		int pre = 0;
		boolean used = false;
		for(int i=0;i<prices.length-1;i++){
			pre = prices[i+1]-prices[i];
			if(pre > 0 && used == false){
				front = prices[i];
				used =true;
			}
			if(pre<0 && used == true){
				count = count + prices[i] - front;
				used =false;
			}
		}
		if(prices[prices.length-1]>front && used == true ){
			count = count + prices[prices.length-1] - front;
		}
		return count;
    }
}
class Solution {
    public int maxProfit(int[] prices) {
        int count =0;
		int pre =0;
		for(int i=1;i<prices.length;i++){
			pre = prices[i]-prices[i-1];
			if(pre > 0){
				count = count + pre;
			}
		}

		return count;
    }
}

55. 跳跃游戏

题目描述

给定一个非负整数数组 nums,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个位置。


解题思路

  1. 方法一:贪心算法(手动模拟最大跳跃)

    • 维护一个变量 maxcount,记录当前可以跳跃的最大距离。
    • 遍历数组:
      • 如果当前位置的最大跳跃值 nums[i] 大于 maxcount,则更新 maxcount
      • 如果 nums.length - 1 - i <= maxcount,说明可以跳到最后一个位置,直接返回 true
      • 如果 maxcount 减少到 0,说明无法继续前进,返回 false
    • 时间复杂度:O(n),空间复杂度:O(1)。
  2. 方法二:覆盖范围法

    • 维护一个变量 coverRange,表示当前能覆盖的最远位置。
    • 遍历数组:
      • 对每个位置 i,更新 coverRange = Math.max(coverRange, nums[i] + i)
      • 如果 coverRange 已经大于或等于数组的最后一个位置,则返回 true
      • 如果遍历到 coverRange 之外的位置,说明无法到达最后一个位置,返回 false
    • 时间复杂度:O(n),空间复杂度:O(1)。

Java代码

class Solution {
    public boolean canJump(int[] nums) {
		int count = 0;
		int maxcount = 0;
		for(int i=0;i<nums.length-1;i++){
			if(maxcount<nums[i]){
				maxcount = nums[i];
			}
			if(nums.length-1-i<maxcount){
				return true;
			}
			if(maxcount<=0){
				return false;
			}
			maxcount--;
		}
		return true;

    }
}
class Solution {
    public boolean canJump(int[] nums) {
		if (nums.length == 1) {
			return true;
		}
		int coverRange = 0;
		for(int i=0;i <= coverRange;i++){
			coverRange = Math.max(coverRange,nums[i]+i);
			if (coverRange >= nums.length-1){
				return true;
			}
		}
		return false;

    }
}

45. 跳跃游戏 II

题目描述

给定一个非负整数数组 nums,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

目标是使用最少的跳跃次数到达数组的最后一个位置。


解题思路

  1. 贪心算法
    • 维护两个变量:
      • coverRange:当前跳跃范围。
      • maxcoverRange:在当前范围内能跳跃到的最远距离。
    • 遍历数组:
      • 如果 maxcoverRange 超过当前 coverRange,更新 coverRange = maxcoverRange,并增加跳跃次数 count++
      • 如果 coverRange 已经覆盖到数组的最后一个位置,则退出循环。
    • 时间复杂度:O(n),空间复杂度:O(1)。

Java代码

class Solution {
    public int jump(int[] nums) {
        if(nums.length<2){
			return nums.length-1;
		}
		int coverRange = 0;
		int maxcoverRange = 0;
		int count = 0;
		for(int i = 0;i<=coverRange;i++){
			if(maxcoverRange<i+nums[i]){
				maxcoverRange = i+nums[i];
			}
			if(coverRange <=i && maxcoverRange > coverRange ){
				coverRange = maxcoverRange;
				count++;
			}
			if(coverRange >= nums.length-1){
				break;
			}
		}
		return count;
    }
}

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

题目描述

给定一个整数数组 nums,我们只能用以下方法修改该数组:
选择某个索引 i 并将 nums[i] 替换为 -nums[i],然后总共重复这个过程 K 次。(可以多次选择同一个索引 i。)

以这种方式修改数组后,返回数组可能的最大和。


解题思路

  1. 方法一:排序+贪心

    • 对数组进行从小到大排序。
    • 遍历数组,将负数变为正数,尽量减少负值,减少 K 的次数。
    • 如果 K 还有剩余,且剩余为奇数,需要对最小值取反一次。
    • 重新计算数组的总和并返回。
  2. 方法二:按绝对值排序+贪心

    • 按数组元素绝对值从大到小排序,优先处理绝对值最大的元素。
    • 遍历数组,将负数变为正数,减少 K 的次数。
    • 如果 K 还有剩余,且为奇数,对绝对值最小的元素取反。
    • 最后计算数组的总和。

Java代码

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
		Arrays.sort(nums);
		int i = 0;
        for(i = 0;i<k && i<nums.length && nums[i] < 0;i++){
			nums[i] = -nums[i];
		}
		if(k>i && (k-i)%2!=0){
			Arrays.sort(nums);
			nums[0] = -nums[0];
		}
		int sum = 0;
		for(i = 0;i<nums.length;i++){
			sum = sum + nums[i];
		}
		return sum;
    }
}
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 < nums.length;i++){
			if(nums[i]<0 && k>0){
				nums[i] = -nums[i];
				k--;
			}
		}
		if(k%2!=0) nums[len-1] = -nums[len-1];
		return Arrays.stream(nums).sum();
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值