Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
现在前端很多岗位面试需要有一定的算法基础,或者说经常刷算法的会优先考虑。
因此每天刷刷LeetCode非常有必要
在这之前我也刷过一些算法题,也希望以后也坚持刷,跟某掘友一样,我也想刷穿 LeetCode
一、题目描述
给你一个整数数组 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] 。
二、思路分析
此处撰写解题思路 这题比较简单,首先计算nums中负数的数量less, 然后拆解开来一共就三种情况
k 比less小,这种情况只需要把负数中的k个最小值翻转一下就可以了
k 比less大,这种情况又分两种
2.1 余数是偶数的情况,证明可以把所有的负数翻转为正数,余数偶数就是再连续翻转两次,值不变,所以计算所有数字的绝对值相加即可
2.2 余数是奇数的情况,这种情况最复杂,前期同 2.1 一样,把所有绝对值加一起,然后需要额外多翻转一次,也就是找到绝对值中最接近 0 的数字,这有两种方法
2.2.1 一是重新把 nums 按照绝对值排序,取 0
2.2.2 二是在2.2 绝对值累加的时候通过增加一个min变量作为中继条件存储我采用的是这种方法
三、代码实现
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var largestSumAfterKNegations = function (nums, k) {
// 1.异常情况,k = 0的情况,不过按照题目描述可以不需要
if (k === 0) return nums.reduce((l, i) => l += i, 0)
// 2.先把数组排个序,方便后续处理 k < less 的翻转
nums.sort((a, b) => a - b)
// 3. 计算 <0 的数字的数量
const less = nums.filter(a => a < 0).length
if (k < less) {
// 如果<0 的数字比可以翻转的步数多,同题解1,直接翻转排序后的前 k 个,累加就可以了
for (let i = 0; i < k; i++) {
nums[i] = -nums[i]
}
return nums.reduce((l, i) => l += i, 0)
} else {
// 如果 <0 的比翻转的少, 同题解 2.2 分成两组条件,由于我采用了2.2.2 的方法,可以提前把数字的绝对值累加到一起赋值 t
let min = 999999
const t = nums.reduce((l, i) => {
l += Math.abs(i)
if (Math.abs(i) < min) {
min = Math.abs(i)
}
return l
}, 0)
// 这里是 2.1 的判定条件,如果(k - less) % 2 === 0 也就是把所有的负数翻转成正数之后额外需要翻转偶数次,最终结果还是都是正数,把刚才的绝对值直接返回去就行了
if ((k - less) % 2 === 0) {
return t
} else {
// 这里是2.2.2 的判定条件,直接减去 2 * min, 因为刚才计算 t 的时候多加了一个 min ,同时 min 应该为负数,所以减去2 min
return t - 2 * min
}
}
};
四、总结
以上就是本道题的所有内容了,本系列会持续更,欢迎点赞、关注、收藏,另外如有其他的问题,欢迎下方留言给我,我会第一时间回复你,感谢~