leetcode每日一题:1005. K 次取反后最大化的数组和
系列:贪心算法
语言:java
题目来源:Leetcode1005. K 次取反后最大化的数组和
题目
给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:
选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。
重复这个过程恰好 k 次。可以多次选择同一个下标 i 。
以这种方式修改数组后,返回数组 可能的最大和 。
示例 1:
输入:nums = [4,2,3], k = 1
输出:5
解释:选择下标 1 ,nums 变为 [4,-2,3] 。
示例 2:
输入:nums = [3,-1,0,2], k = 3
输出:6
解释:选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2] 。
示例 3:
输入:nums = [2,-3,-1,5,-4], k = 2
输出:13
解释:选择下标 (1, 4) ,nums 变为 [2,3,-1,5,4] 。
约束条件:
1 <= nums.length <= 104
-100 <= nums[i] <= 100
1 <= k <= 104
思路:
分析:通过题目和例题我们了解到本题是通过规定次数内的反转操作来使所求的数组和最大。
思路:本题可以直接写或者贪心法解决。
直接法:通过排序,从小到大排序数据,如果k的数够大,将负数都转为正数的话,那么进行二次排序从小到大,对剩余的k进行取余操作,只对最小的那个数进行翻转。下面看具体代码实现:
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
// 常规方法
Arrays.sort(nums);
int count = 0;
for(int i =0;i<nums.length;i++){
if(k>0 && nums[i]<0){
nums[i] = -nums[i];
k--;
}
count +=nums[i];
}
//二次排序
Arrays.sort(nums);
if(k>0){
//这一块有点难理解
//因为上面已经求了总和,现在看k是否是偶数,偶数的话就原封不动,奇数的话减去2倍值才能等价于 加上对它进行取反操作求和
return count-(k%2==0?0:2*nums[0]);
}
return count;
}
}
贪心法:每走一步都满足最大,最后可以达到最大和,所以我们需要对数组中的数进行排序,按照绝对值大小进行逆向排序,java中自带方法如下:进行排序
nums = IntStream.of(nums)
.boxed()
.sorted((o1,o2) -> Math.abs(o2)-Math.abs(o1))
.mapToInt(Integer::intValue).toArray();
同时部分思路也有部分如同第一种方法,具体代码实现如下:
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 num = 0;
for(int i =0;i<nums.length;i++){
if(nums[i]<0 && k>0){
nums[i] = -nums[i];
k--;
}
num+=nums[i];
}
if(k>0){
return num-(k%2==0?0:2*nums[nums.length-1]);
}
return num;
}
}
感谢您的阅读,希望对您有所帮助。关注我,完成每日算法自律打卡,什么时候开始都不晚!!