题目链接:122.买卖股票的最佳时机II
文档讲解:代码随想录
状态:so easy
思路:不用考虑操作的次数,其实只要有赚就拿下就行了。
题解:
class Solution {
public int maxProfit(int[] prices) {
// 初始化一个数组 dp 用于记录每一天的累计利润
int[] dp = new int[prices.length];
// 从第二天开始遍历价格数组
for (int i = 1; i < prices.length; i++) {
// 如果当天的价格比前一天高,则计算利润;否则利润为 0
int profit = prices[i] > prices[i - 1] ? prices[i] - prices[i - 1] : 0;
// 当天的累计利润等于前一天的累计利润加上当天的利润
dp[i] = dp[i - 1] + profit;
}
// 返回在最后一天的累计最大利润
return dp[prices.length - 1];
}
}
思路:贪心策略的核心思想是在遍历数组的过程中,始终维护当前能够到达的最远位置,并尽量往前跳。只要当前能够到达的最远位置始终大于等于当前位置,就说明可以到达最后一个位置。否则,就不能到达。
题解:
public boolean canJump(int[] nums) {
// 记录当前能够到达的最远位置
int maxReach = nums[0];
// 遍历数组
for (int i = 1; i < nums.length; i++) {
// 如果当前最远距离小于当前位置,说明无法到达当前位置,返回 false
if (maxReach < i) {
return false;
}
// 更新当前能够到达的最远位置
maxReach = Math.max(maxReach, nums[i] + i);
// 如果最远位置已经到达或超过最后一个位置,返回 true
if (maxReach >= nums.length - 1) {
return true;
}
}
// 如果遍历结束后无法到达最后一个位置,返回 false
return maxReach >= nums.length - 1;
}
思路:在每一步选择能够跳跃到最远位置的点,从而逐步向数组的末尾移动。
题解:
public int jump(int[] nums) {
// 记录能够到达的最远位置
int maxReach = 0;
// 记录当前步数的结束位置
int end = 0;
// 记录跳跃次数
int res = 0;
// 遍历数组,尝试每一步能到达的最远位置
int i = 0;
while (i < nums.length - 1) {
// 更新能够到达的最远位置
maxReach = Math.max(maxReach, nums[i] + i);
// 如果当前步数达到了之前设定的结束位置
if (i == end) {
// 更新结束位置为当前能够到达的最远位置
end = maxReach;
// 增加跳跃次数
res++;
}
// 继续遍历下一个位置
i++;
}
// 返回跳跃次数
return res;
}
题目链接:1005.K次取反后最大化的数组和
文档讲解:代码随想录
状态:好烦,总是各种想漏了!
思路:当负数的个数大于等于k时,翻转所有负数,如果k还有剩余次数,则说明负数已经全部转正,此时剩余的k个数如果是偶数则自己抵消,如果是奇数就减掉2倍最小正数。
题解:
public int largestSumAfterKNegations(int[] nums, int k) {
// 排序,把可能有的负数排到前面
Arrays.sort(nums);
int sum = 0;
for (int i = 0; i < nums.length; i++) {
// 贪心:当负数的个数大于等于k时,翻转所有负数,如果k还有剩余次数,则说明负数已经全部转正,此时剩余的k个数如果是偶数则自己抵消,如果是奇数就减掉2倍最小正数
if (nums[i] < 0 && k > 0) {
nums[i] = -1 * nums[i];
k--;
}
sum += nums[i];
}
Arrays.sort(nums);
// 如果k没剩,那说明能转的负数都转正了,已经是最大和,返回sum
// 如果k有剩,说明负数已经全部转正,所以如果k还剩偶数个就自己抵消掉,不用删减,如果k还剩奇数个就减掉2倍最小正数。
return sum - (k % 2 == 0 ? 0 : 2 * nums[0]);
}