[leetcode][1005]K 次取反后最大化的数组和
1.题目描述
//给你一个整数数组 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 // // Related Topics 贪心 数组 排序 // 👍 211 👎 0
2.我的解体思路
翻译下题目的意思就是,k次对某一个数组元素取反,使得数组所有元素的和最大。
首先容易想到的就是,我把所有的负数都翻成正数,就能使得数组的和最大了,于是就可以从最小的负数开始,依次翻成正数。
但是会出现所有的负数都翻完了,但是还没达到k次的要求。这时就只能忍痛割爱,把最小的正数翻成负数。
经过上面一顿分析,发现有个关键词,最小。就是每次都是需要取反转最小的那个数,一提到最小,脑中就出现一种数据结构,最小堆。
好了,再翻译下题目的意思就就变成了:对给定数组中最小的数取反,执行k次。当最小的数是0的时候,直接结束取反操作。
最后再sum下所有的元素就大功告成了。
3.代码实现
class Solution { int[] smallHeap; int heapSize = 0; public int largestSumAfterKNegations(int[] nums, int k) { smallHeap = new int[nums.length + 5]; for (int num : nums) { addElm(num); } int smallValue; while (k > 0) { if (top() == 0) { break; } else { smallValue = -1 * pop(); addElm(smallValue); k--; } } int sum = 0; for (int i = 0; i < heapSize; i++) { sum += smallHeap[i]; } return sum; } private void addElm(int newValue) { smallHeap[heapSize++] = newValue; if (heapSize == 1) { return; } int idx = heapSize - 1; int fIdx = (idx - 1) / 2; int tmp; while (idx > 0) { if (smallHeap[idx] < smallHeap[fIdx]) { tmp = smallHeap[fIdx]; smallHeap[fIdx] = smallHeap[idx]; smallHeap[idx] = tmp; idx = fIdx; fIdx = (idx - 1) / 2; } else { break; } } } private int top() { return smallHeap[0]; } private int pop() { int topValue = smallHeap[0]; smallHeap[0] = smallHeap[--heapSize]; int idx = 0; int lIdx = idx * 2 + 1; int rIdx = (idx + 1) * 2; while (idx < heapSize) { // 有两个子节点 if (lIdx < heapSize && rIdx < heapSize) { // 两个子节点都比当前节点小 if (smallHeap[lIdx] < smallHeap[idx] && smallHeap[rIdx] < smallHeap[idx]) { if (smallHeap[lIdx] < smallHeap[rIdx]) { idx = changePos(idx, lIdx); } else { idx = changePos(idx, rIdx); } } else { if (smallHeap[lIdx] < smallHeap[idx]) { idx = changePos(idx, lIdx); } else if (smallHeap[rIdx] < smallHeap[idx]) { idx = changePos(idx, rIdx); } else { break; } } } else if (lIdx < heapSize && rIdx >= heapSize) { if (smallHeap[lIdx] < smallHeap[idx]) { idx = changePos(idx, lIdx); } else { break; } } else { break; } lIdx = idx * 2 + 1; rIdx = (idx + 1) * 2; } return topValue; } private int changePos(int idx1, int idx2) { int tmp = smallHeap[idx1]; smallHeap[idx1] = smallHeap[idx2]; smallHeap[idx2] = tmp; return idx2; } }