LeetCode周赛216C: 5607. 生成平衡数组的方案数
看了一下数据范围
这道题暴力应该是解不出来的, 最后用暴力试了一下,不出所料的超时了。
没关系。一般解法都是从暴力入手,找办法优化的。 沖(chong)
发现好像可以通过前缀和快速的进行结果的计算
思路:
先将给出的数组按下标的奇数位、偶数位的前缀和计算出来。
给定的数组nums: [ 1 , 1 , 1 , 1 , 1 ] [1,1,1,1,1] [1,1,1,1,1]
前缀和preSum: [ 1 , 1 , 2 , 2 , 3 ] [1,1,2,2,3] [1,1,2,2,3]
小贴士: 因为删掉了一个数,所以删掉的该数后面的所有下标都向前移动 1 , 奇变偶, 偶变奇
然后我们会发现: 删除当前位置的下标 ( i n d e x = 3 ) (index = 3) (index=3)时
奇数位上的和就等于: i n d e x = 3 之 前 的 所 有 奇 数 位 和 + i n d e x = 3 之 后 的 所 有 偶 数 位 的 和 index = 3 之前的所有奇数位和 + index =3 之后的所有偶数位的和 index=3之前的所有奇数位和+index=3之后的所有偶数位的和
偶数位上的和就等于: i n d e x = 2 之 前 的 所 有 偶 数 位 和 + i n d e x = 3 之 后 的 所 有 奇 数 位 的 和 index = 2 之前的所有偶数位和 + index = 3 之后的所有奇数位的和 index=2之前的所有偶数位和+index=3之后的所有奇数位的和
整体由普通思路 >> 再考虑特定的边界条件
小贴士: 可以再同时计算给定数组的sum, 当删掉一个数后 sum - num 如果为奇数,奇数位和 and 偶数位和必不可能相等。
提前进入下一次循环
AC Code
奇偶前缀和
public int waysToMakeFair(int[] nums) {
if(nums.length == 1) return 1;
int ans = 0;
int sum = 0;
int[] preSum = new int[nums.length];
preSum[0] = nums[0]; preSum[1] = nums[1]; sum += (nums[0] + nums[1]);
for (int i = 2; i < nums.length; i++) {
sum += nums[i];
if(i % 2 == 1) preSum[i] = preSum[i - 2] + nums[i];
else preSum[i] = preSum[i - 2] + nums[i];
}
// System.out.println(Arrays.toString(preSum));
for (int i = 0; i < nums.length; i++) {
// 为奇数不可能相等
if((sum - nums[i]) % 2 == 1) continue;
int asum = 0, bsum = 0;
// 2 1 8 5
// 0 1 2 3 (index
if(i - 1 >= 0)
asum += preSum[i - 1]; // 奇
if(i - 2 >= 0)
bsum += preSum[i - 2]; // 偶
if(i % 2 == (nums.length - 1) % 2){
// 当 i 为奇数的时候,那么 asum 之前就是偶位数的和 >> 后面就加 奇数位 的和
asum += preSum[nums.length - 1] - preSum[i];
if(i - 1 >= 0)
bsum += preSum[nums.length - 2] - preSum[i - 1];
else bsum += preSum[nums.length - 2];
} else {
// 当 i 为奇数的时候。asum 之前就是 偶位数的和, 且 nums.length - 1为偶数, 所以后面要加 奇数位 的和
asum += preSum[nums.length - 2] - preSum[i];
if(i - 1 >= 0)
bsum += preSum[nums.length - 1] - preSum[i - 1];
else bsum += preSum[nums.length - 1] ;
}
if(asum == bsum) ans++;
}
return ans;
}
暴力不出意料的 超时了
超时数据: 超时样例
public int waysToMakeFair(int[] nums) {
int ans = 0;
for (int i = 0; i < nums.length; i++) {
int evenSum = 0, oddSum = 0;
for (int j = 0; j < nums.length; j++) {
if(j < i){
if(j % 2 == 0) evenSum += nums[j];
else oddSum += nums[j];
} else if(j > i){
if((j -1) % 2 == 0) evenSum += nums[j];
else oddSum += nums[j];
}
// == 不管
}
if(oddSum == evenSum) ans++;
}
return ans;
}
虽然花了两个小时, 但还是做出来了,问题不大.
这么久的原因是因为 生成前缀和数组的时候写错了 主干没啥问题。