Easy
题目描述
给你一个长度为 n 的整数数组 nums。
分割定义为索引 i,其中 0 <= i < n - 1,将数组分为两个非空子数组:
- 左子数组包含索引
[0, i] - 右子数组包含索引
[i + 1, n - 1]
返回左右子数组和的差值为偶数的分割数量。
示例 1:
输入: nums = [10,10,3,7,6]
输出: 4
解释:
这 4 个分割是:
- [10], [10, 3, 7, 6] 和的差值为 10 - 26 = -16,是偶数
- [10, 10], [3, 7, 6] 和的差值为 20 - 16 = 4,是偶数
- [10, 10, 3], [7, 6] 和的差值为 23 - 13 = 10,是偶数
- [10, 10, 3, 7], [6] 和的差值为 30 - 6 = 24,是偶数
示例 2:
输入: nums = [1,2,2]
输出: 0
解释:
没有分割会产生偶数和差值。
示例 3:
输入: nums = [2,4,6,8]
输出: 3
解释:
所有分割都会产生偶数和差值。
约束条件:
2 <= n == nums.length <= 1001 <= nums[i] <= 100
解题思路
这道题的关键洞察是:两个数的差值为偶数,当且仅当这两个数的奇偶性相同(都是奇数或都是偶数)。
因此我们可以通过以下数学推导来简化问题:
- 设左子数组和为
leftSum,右子数组和为rightSum - 总和
totalSum = leftSum + rightSum - 差值
diff = leftSum - rightSum = leftSum - (totalSum - leftSum) = 2 * leftSum - totalSum
要使差值为偶数,需要 2 * leftSum - totalSum 为偶数。由于 2 * leftSum 总是偶数,所以需要 totalSum 也为偶数。
关键发现:如果总和为奇数,则不存在任何有效分割;如果总和为偶数,则所有分割都有效。
这是因为当总和为偶数时,对于任意分割点,左子数组和与右子数组和的奇偶性必然相同,它们的差值就是偶数。
算法步骤:
- 计算数组总和
- 如果总和为奇数,返回 0
- 如果总和为偶数,返回
n-1(即所有可能的分割数)
时间复杂度:O(n),空间复杂度:O(1)。
代码实现
class Solution {
public:
int countPartitions(vector<int>& nums) {
int totalSum = 0;
for (int num : nums) {
totalSum += num;
}
// 如果总和为奇数,不存在有效分割
if (totalSum % 2 == 1) {
return 0;
}
// 如果总和为偶数,所有分割都有效
return nums.size() - 1;
}
};
class Solution:
def countPartitions(self, nums: List[int]) -> int:
total_sum = sum(nums)
# 如果总和为奇数,不存在有效分割
if total_sum % 2 == 1:
return 0
# 如果总和为偶数,所有分割都有效
return len(nums) - 1
public class Solution {
public int CountPartitions(int[] nums) {
int totalSum = nums.Sum();
// 如果总和为奇数,不存在有效分割
if (totalSum % 2 == 1) {
return 0;
}
// 如果总和为偶数,所有分割都有效
return nums.Length - 1;
}
}
/**
* @param {number[]} nums
* @return {number}
*/
var countPartitions = function(nums) {
const n = nums.length;
const totalSum = nums.reduce((sum, num) => sum + num, 0);
let leftSum = 0;
let count = 0;
for (let i = 0; i < n - 1; i++) {
leftSum += nums[i];
const rightSum = totalSum - leftSum;
const diff = leftSum - rightSum;
if (diff % 2 === 0) {
count++;
}
}
return count;
};
复杂度分析
| 复杂度类型 | 数值 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历一次数组计算总和 |
| 空间复杂度 | O(1) | 只使用常数额外空间 |