买卖股票的最佳时机 II
题目链接:122. 买卖股票的最佳时机 II
解题逻辑:
本题的局部最优在于:当前持有的股票如果明天继续持有赚的没有今天多或者还亏了,那么今天就抛售
class Solution {
public int maxProfit(int[] prices) {
boolean buy = true;
int sum = 0;
int maxSum = Integer.MIN_VALUE;
for(int i = 0;i < prices.length;i++) {
if(buy) {
sum -= prices[i];
buy = false;
}
if(i + 1 < prices.length && prices[i + 1] > prices[i]) continue;
sum += prices[i];
if(sum > maxSum) maxSum = sum;
buy = true;
}
return maxSum;
}
}
跳跃游戏
题目链接:55. 跳跃游戏
解题逻辑:
使用队列,这个队列的作用就是维护一个能够到达的区间(有点层序遍历二叉树的味道)
这个方法的思想是先将数组的第一个元素(也就是起点)能够到达的元素入队,接下来如果队头能够到达的元素在队列中,那么就将这个元素弹出去。而如果队头所能到达的元素不在队列中,则将数组中对应的元素入队。如此若最后数组中还有元素没有入队则返回false,其余情况返回true。
代码如下:
class Solution {
public boolean canJump(int[] nums) {
int pointer = 0;
Deque<Integer> queue = new ArrayDeque<>();
if(nums[pointer] + 1 >= nums.length) return true;
int addNum = nums[pointer] + 1;
for(int i = 0;i < addNum;i++) queue.add(nums[pointer++]);
while(!queue.isEmpty()) {
if(queue.element() + 1 <= queue.size()) queue.remove();
else {
int need = queue.element() + 1 - queue.size();
if(need > nums.length - pointer) return true;
for(int i = 0;i < need;i++) queue.add(nums[pointer++]);
}
}
if(pointer >= nums.length) return true;
return false;
}
}
跳跃游戏 II
题目链接:45. 跳跃游戏 II
本题的贪心贪的是什么?这里很容易陷入一个误区那就是贪得是跳跃的长度,也就是每次都选跳跃长度最长的,这样最后跳跃的次数肯定也少。
但是此题真正应该贪得是跳跃的距离,每次取最长的距离,如此最后才会保证跳跃的次数最少。
从代码上来说跳跃的长度是nums[i],而跳跃的距离就是nums[i] + i
解题逻辑:
- 初始化双指针left、right代表当前所能到达的范围
- 在该区间中找到跳跃距离最远的点作为下一跳
- 计数
- 如此循环直到right >= nums.length - 1为止
class Solution {
public int jump(int[] nums) {
if(nums.length == 1) return 0;
int count = 0;
int nextJump = 0;
while(true) {
int left = nextJump;
int right = nums[left] + left;
if(right >= nums.length - 1) return count + 1;
int maxIndex = 0;
for(int i = left;i <= right;i++) {
int currentIndex = nums[i] + i;
if(currentIndex>= maxIndex) {
maxIndex = currentIndex;
nextJump = i;
}
}
count++;
}
}
}
K次取反后最大化的数组和
题目链接:1005. K 次取反后最大化的数组和
解题逻辑:
这道题的局部最优很好想就是将这个取反给最小的负数即可,没有负数或者有多余的取反操作则给最小的正数即可。
解题代码:
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
Arrays.sort(nums);
int negative = 0;
for(int num : nums) if(num < 0) negative++;
if(k <= negative) for(int i = 0;i < k;i++) nums[i] = -nums[i];
else {
int result = (k - negative) % 2;
if(result == 0) for(int i = 0;i < negative;i++) nums[i] = -nums[i];
else {
if(negative == 0) nums[0] = -nums[0];
else {
for(int i = 0;i < negative;i++) nums[i] = -nums[i];
int num1 = nums[negative - 1];
int num2 = Integer.MAX_VALUE;
if(negative < nums.length) num2 = nums[negative];
int index = num1 > num2 ? negative : negative - 1;
nums[index] = -nums[index];
}
}
}
int sum = 0;
for(int num : nums) sum += num;
return sum;
}
}