一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情。
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【LeetCode 1664. 生成平衡数组的方案数 】- JavaScript(动态规划+前缀和)
题意描述
给你一个整数数组 nums 。你需要选择 恰好 一个下标(下标从 0 开始)并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。
比方说,如果 nums = [6,1,7,4,1] ,那么:
选择删除下标 1 ,剩下的数组为 nums = [6,7,4,1] 。
选择删除下标 2 ,剩下的数组为 nums = [6,1,4,1] 。
选择删除下标 4 ,剩下的数组为 nums = [6,1,7,4] 。
如果一个数组满足奇数下标元素的和与偶数下标元素的和相等,该数组就是一个 平衡数组 。
请你返回删除操作后,剩下的数组 nums 是 平衡数组 的 方案数 。
示例 1:
输入:nums = [2,1,6,4] 输出:1 解释: 删除下标 0 :[1,6,4] -> 偶数元素下标为:1 + 4 = 5 。奇数元素下标为:6 。不平衡。 删除下标 1 :[2,6,4] -> 偶数元素下标为:2 + 4 = 6 。奇数元素下标为:6 。平衡。 删除下标 2 :[2,1,4] -> 偶数元素下标为:2 + 4 = 6 。奇数元素下标为:1 。不平衡。 删除下标 3 :[2,1,6] -> 偶数元素下标为:2 + 6 = 8 。奇数元素下标为:1 。不平衡。 只有一种让剩余数组成为平衡数组的方案。
思路分析:
首先我们先来分析一下这一道题 题目需要我们在数组中删除任意一个数字后,奇数和偶数位置上的数字求和数值相等。 我们可以使用暴力算法直接删除循环后+求和也可以得出答案。
动态规划
首先构建dp数组,其含义是从i开始到数组结尾的偶数下标元素-奇数下标元素。
dp[0]==0即为平衡数组。对于一个删除操作,对整个数组dp值(即dp[0])的影响分为两个部分:一是该元素消失了,二是该下标之后的元素的奇偶性全部对调。
var waysToMakeFair = function(nums) {
var isBalance = function (arr) {
let result = 0
for (let i = 1; i < arr.length; i++) {
i % 2
? result += arr[i]
: result -= arr[i]
}
return result
}
let result = 0, dp
for (let i = 0; i < nums.length; i++) {
if (dp === undefined) {
dp = isBalance(nums)
} else {
i % 2
? dp += (nums[i - 1] - nums[i])
: dp -= (nums[i - 1] - nums[i])
}
!dp && result ++
}
return result
};
前缀和
思路:
- 数组存储偶数位与奇数位的前缀差和
- 删除 i ,i后 偶奇位 变 奇偶位,即f[n] - f[i] 为 i+1 ~ n 的奇偶差
- 要求奇位和 == 偶位和,则转化为 偶奇差 == 0
- 将 i 后的偶奇差移到等式右边,则满足 f[i-1] == f[n] - f[i]
var waysToMakeFair = function (nums) {
const n = nums.length;
const sum = [0, 0];
for (let i = 0; i < n; i++) {
sum[i % 2] += nums[i];
}
let res = 0;
const cur = [0, 0];
for (let i = 0; i < n; i++) {
const o = sum[0] - cur[0];
const e = sum[1] - cur[1];
if (i & 1) {
if (cur[0] + e - nums[i] === cur[1] + o) res++;
} else {
if (cur[0] + e === cur[1] + o - nums[i]) res++;
}
cur[i % 2] += nums[i];
}
return res;
};
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤