今日收获:买卖股票的最佳时机II,跳跃游戏,跳跃游戏Ⅱ,K次取反后最大化的数组和
1. 买卖股票的最佳时机II
题目链接:122. 买卖股票的最佳时机 II - 力扣(LeetCode)
思路:收集每天的正利润(局部最优),如果这天亏了就不收集。重点是有一个思路上的转变,将最低买入和最高卖出,转化为收集每一天的利润。
方法:
class Solution {
public int maxProfit(int[] prices) {
int max=0;
int len=prices.length;
for (int i=1;i<len;i++){
if ((prices[i]-prices[i-1])>0){
max+=prices[i]-prices[i-1];
}
}
return max;
}
}
2. 跳跃游戏
思路:将每一个元素的位置和元素值相加就是本位置能达到的最大覆盖范围(局部最优),不断更新最大覆盖范围,判断覆盖范围能不能到达终点(全局最优)。注意只能在覆盖范围中跳跃,即覆盖范围就是循环的终止条件。
方法:
class Solution {
public boolean canJump(int[] nums) {
int cover=0;
int len=nums.length;
for (int i=0;i<=cover;i++){
cover=Math.max(i+nums[i],cover); // 覆盖范围
if (cover>=(len-1)){
return true;
}
}
return false;
}
}
3. 跳跃游戏Ⅱ
题目链接:45. 跳跃游戏 II - 力扣(LeetCode)
思路:每一步都尽可能求最大的覆盖范围(局部最优)。如果当前步中的最大覆盖范围都没有到达终点(此时走到了当前步覆盖范围的尽头),就将最大覆盖范围作为当前步的覆盖范围,此时步数再加1。
方法:
class Solution {
public int jump(int[] nums) {
int count=0;
int curCover=0; // 处在0的位置肯定要跳一步,除非长度为0
int maxCover=0;
if (nums.length==1){
return 0;
}
for (int i=0;i<nums.length;i++){
maxCover=Math.max(maxCover,i+nums[i]);
// 差最后一步可以跳到终点
if (maxCover>=(nums.length-1)){
count++;
break;
}
if (i==curCover){ // 最大覆盖范围还不到,就要再跳
curCover=maxCover;
count++;
}
}
return count;
}
}
4. K次取反后最大化的数组和
题目链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)
思路:先将k尽可能作用于较大的负数反转(一次贪心),如果还有剩余,就全部作用在最小的正数上(两次贪心)
方法:
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
Arrays.sort(nums);
// 先处理负数
for (int i=0;i<nums.length;i++){
if (nums[i]<0&&k>0){
nums[i]*=-1;
k--;
}
}
Arrays.sort(nums);
// 将k作用于最小正数
if (k>0&&k%2==1){
nums[0]*=-1;
}
// 计算数组总和
int sum=0;
for (int i=0;i<nums.length;i++){
sum+=nums[i];
}
return sum;
}
}