本文主要是介绍【LeetCode】1005. K 次取反后最大化的数组和(简单)——代码随想录算法训练营Day33,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题目链接:1005. 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
文章讲解:代码随想录
视频讲解:贪心算法,这不就是常识?还能叫贪心?LeetCode:1005.K次取反后最大化的数组和_哔哩哔哩_bilibili
题解1:暴力法
思路:先翻转负数,再翻转0,然后翻转正数,需要处理多种细节。
/*** @param {number[]} nums* @param {number} k* @return {number}*/
var largestSumAfterKNegations = function(nums, k) {nums.sort((a, b) => a - b);let sum = 0;// 翻转负数let i = 0;while (i < nums.length && nums[i] < 0 && k--) {sum += -nums[i++];}// 消耗多余翻转次数if (k > 0 && i < nums.length) {if (nums[i] === 0) {// 翻转0k = 0;} else {// 翻转正数if (i === 0) {sum -= nums[i];} else {if (k % 2 === 1) {if (nums[i] <= -nums[i - 1]) {sum -= nums[i];} else {sum += 2 * nums[i - 1] + nums[i];}} else {sum += nums[i];}}}i++;} else if (k > 0) {if (k % 2 === 1) {sum += 2 * nums[i - 1];}}while (i < nums.length) {sum += nums[i++];}return sum;
};
分析:时间复杂度为 O(nlogn),空间复杂度为 O(1)。
题解2:贪心算法
思路:先对数组按绝对值进行降序排列,进行两次贪心策略,先翻转负数,如果次数还有剩余,此时数组中全是非负数,然后翻转最小的非负数。
/*** @param {number[]} nums* @param {number} k* @return {number}*/
var largestSumAfterKNegations = function(nums, k) {// 将数组按绝对值降序排序nums.sort((a, b) => Math.abs(b) - Math.abs(a));// 翻转负数nums = nums.map((num) => k > 0 && num < 0 && k-- && -num || num);// 翻转正数if (k % 2 === 1) {nums[nums.length - 1] = -nums[nums.length - 1];}return nums.reduce((a, b) => a + b);
};
分析:时间复杂度为 O(nlogn),空间复杂度为 O(1)。
收获
贪心算法的套路并不固定,有些题目需要使用两次贪心策略,要注意以局部最优到全局最优的角度思考问题。
这篇关于【LeetCode】1005. K 次取反后最大化的数组和(简单)——代码随想录算法训练营Day33的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!