LeetCode 1664. Ways to Make a Fair Array
题目描述
给你一个整数数组 nums。你需要恰好移除一个元素后,使得剩余元素中,奇数下标元素之和等于偶数下标元素之和。返回满足条件的移除方案数。
例如:nums = [2,1,6,4],输出 1。
解释:
- 移除下标 0:
[1,6,4],偶数下标和 = 1+4=5,奇数下标和 = 6,5 ≠ 6 - 移除下标 1:
[2,6,4],偶数下标和 = 2+4=6,奇数下标和 = 6,6 = 6 ✓ - 移除下标 2:
[2,1,4],偶数下标和 = 2+4=6,奇数下标和 = 1,6 ≠ 1 - 移除下标 3:
[2,1,6],偶数下标和 = 2+6=8,奇数下标和 = 1,8 ≠ 1
只有移除下标 1 满足条件。
解题思路
核心思想
直接枚举每个元素被移除的情况需要 O(n²)。我们可以用前缀和的思想在 O(n) 时间内解决。
当移除下标 i 的元素后,剩余元素的下标会发生变化:
i之前的元素,其下标奇偶性不变。i之后的元素,其下标奇偶性反转(原来的偶数变奇数,奇数变偶数)。
因此,移除 i 之后:
- 新的偶数下标和 =
i之前的偶数下标和 +i之后的奇数下标和 - 新的奇数下标和 =
i之前的奇数下标和 +i之后的偶数下标和(注意减去被移除的nums[i],如果i是偶数,则从偶数和中减去;如果i是奇数,则从奇数和中减去)
步骤
- 先统计整个数组的偶数下标总和
evenTotal和奇数下标总和oddTotal。 - 遍历数组,维护
evenPrefix(当前元素之前的偶数下标前缀和)和oddPrefix(当前元素之前的奇数下标前缀和)。 - 对于每个下标
i,分两种情况进行计算:- 如果
i是偶数下标:- 移除后偶数下标和 =
evenPrefix+ (i之后的奇数下标总和)=evenPrefix + (oddTotal - oddPrefix) - 移除后奇数下标和 =
oddPrefix+ (i之后的偶数下标总和)-nums[i]=oddPrefix + (evenTotal - evenPrefix - nums[i])
- 移除后偶数下标和 =
- 如果
i是奇数下标:- 移除后偶数下标和 =
evenPrefix+ (i之后的奇数下标总和)-nums[i]=evenPrefix + (oddTotal - oddPrefix - nums[i]) - 移除后奇数下标和 =
oddPrefix+ (i之后的偶数下标总和)=oddPrefix + (evenTotal - evenPrefix)
- 移除后偶数下标和 =
- 如果
- 如果移除后的偶数下标和 == 奇数下标和,ans++。
- 更新
evenPrefix或oddPrefix(根据i的奇偶性)。
示例说明
以 nums = [2,1,6,4] 为例:
- evenTotal = nums[0] + nums[2] = 2 + 6 = 8
- oddTotal = nums[1] + nums[3] = 1 + 4 = 5
- i=0(偶数):新偶 = 0+(5-0) = 5,新奇 = 0+(8-0-2) = 6,5≠6;更新 evenPrefix = 2
- i=1(奇数):新偶 = 2+(5-0-1) = 6,新奇 = 0+(8-2) = 6,6=6 ✓,ans=1;更新 oddPrefix = 1
- i=2(偶数):新偶 = 2+(5-1) = 6,新奇 = 1+(8-2-6) = 1,6≠1;更新 evenPrefix = 8
- i=3(奇数):新偶 = 8+(5-1-4) = 8,新奇 = 1+(8-8) = 1,8≠1;更新 oddPrefix = 5
- 返回 1
复杂度分析
- 时间复杂度:
O(n),两次遍历数组。 - 空间复杂度:
O(1),只使用常数额外空间。
代码
1 | package code.J1664; |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 𝒞𝒶𝓃𝒶𝓇𝓎!