力扣算法学习day23-3
45-跳跃游戏 II
题目
代码实现
class Solution {
// 直接想到并作出的题解 速度 12ms
// public int jump(int[] nums) {
// // 贪心,局部最优 --> 全局最优
// // 首先想的是每次走最大(不为0),但是实例1中很明显说明了不行,然后思考怎么
// // 才能确定局部的最大,发现正序感觉都不行,至少需要使用回溯和递归比较麻烦,但是倒序可以
// // 确定能直接到尾部的距离尾部最远的坐标,同理,继续推到这个点最远的,想不出反例,尝试。
// int count = 0;// 记录跳跃次数
// int index = nums.length-1;
// while(index > 0){
// for(int i = 0;i < nums.length;i++){
// if(i + nums[i] >= index){
// index = i;
// count++;
// break;
// }
// }
// }
// return count;
// }
// 代码随想录思路,贪心,范围扩张的方式.
// 方法二: 速度 2ms,代码更简洁,利用了nums.lengt-2这个位置。方法一没写,方法二基于方法一,差不多。
// public int jump(int[] nums) {
// int count = 0;// 记录跳跃的步骤。
// int curScope = 0;// 当前覆盖范围
// int nextScope = 0;// 下一步覆盖范围
// for(int i = 0;i < nums.length - 1;i++){
// nextScope = Math.max(i+nums[i],nextScope);
// if(i == curScope){
// count++;
// curScope = nextScope;
// }
// }
// return count;
// }
// 个人基于代码随想录思想(差不多),觉得更直接能想到的是范围层扩展,先扩一个的范围,
// 如果没有覆盖最后一个坐标,则将第一个范围的都遍历比较得到第一个范围能到达
// 的第二个范围最大的圈,即每次跳跃扩展一层范围。比较是否覆盖即可。
// 速度 ,差距不大,1ms
public int jump(int[] nums) {
if(nums.length == 1){
return 0;
}
int count = 0;
int index = 0;
int scope = 0;
for(int i = 0;i < nums.length;i++){
scope = Math.max(i+nums[i],scope);
if(i < index){
continue;
}
count++;
if(scope >= nums.length-1){
break;
}
index = scope;
}
return count;
}
}
1005-K 次取反后最大化的数组和
题目
代码实现
class Solution {
// 直接想到解决的方法,速度 2ms
// public int largestSumAfterKNegations(int[] nums, int k) {
// // 贪心,首先排序,将负数尽量变为正数
// Arrays.sort(nums);
// int index = 0;// 用于记录第一个非负数的坐标
// int sum = 0;// 用于记录最大总和。
// for(int i = 0;i < nums.length;i++){
// if(nums[i] < 0 && k > 0){
// nums[i] = -nums[i];
// k--;
// sum += nums[i];
// } else{
// sum += nums[i];
// }
// }
// if(k % 2 == 0){// k <= 负数的数量,k > 负数的数量且k 剩余为偶数。
// return sum;
// } else{// k > 负数的数量且k剩余为奇数
// Arrays.sort(nums);
// sum = sum - 2 * nums[0];
// return sum;
// }
// }
// 速度优化,对第二次排序优化,理论上速度可能会快点,实测一样。
public int largestSumAfterKNegations(int[] nums, int k) {
// 贪心,首先排序,将负数尽量变为正数
Arrays.sort(nums);
int index = 0;// 用于记录第一个非负数的坐标
int sum = 0;// 用于记录最大总和。
for(int i = 0;i < nums.length;i++){
if(nums[i] < 0 && k > 0){
nums[i] = -nums[i];
k--;
sum += nums[i];
index = i;// 记录最后一个负数的坐标。
} else{
sum += nums[i];
}
}
if(k % 2 == 0){// k <= 负数的数量,k > 负数的数量且k 剩余为偶数。
return sum;
} else{// k > 负数的数量且k剩余为奇数
if(index == nums.length-1){
return sum - 2 * nums[nums.length-1];
} else{
int min = Math.min(nums[index],nums[index+1]);
return sum - 2 * min;
}
}
}
}