题目分析
这个问题要求我们找出一个数组可以被分割成两个非空部分的合法分割方案数。一个分割方案是合法的,如果满足以下两个条件:
-
前
i + 1
个元素的和大于等于剩下的n - i - 1
个元素的和。 -
下标
i
的右边至少有一个元素,即0 <= i < n - 1
。
算法思路
-
计算总和:首先计算数组
nums
的总和totalSum
。 -
双指针:使用两个指针
suml
和sumr
分别表示左边部分的和与右边部分的和。初始化suml
为 0,sumr
为totalSum
。 -
遍历数组:从数组的第一个元素开始,逐个添加到
suml
并从sumr
中减去相同的值。 -
判断合法性:在每一步中,如果
suml
大于等于sumr
,则表示当前位置i
是一个合法的分割点。 -
计数:每当找到一个合法的分割点,增加方案计数器
ways
。
代码实现
#include <vector>
class Solution {
public:
int waysToSplitArray(std::vector<int>& nums) {
int n = nums.size();
long long totalSum = 0; // 使用 long long 避免溢出
for (int num : nums) {
totalSum += num;
}
long long suml = 0, sumr = totalSum;
int ways = 0;
for (int i = 0; i < n - 1; ++i) {
suml += nums[i];
sumr -= nums[i];
if (suml >= sumr) {
++ways;
}
}
return ways;
}
};
复杂度分析
-
时间复杂度:O(n),其中 n 是数组
nums
的长度。我们只需要遍历数组一次。 -
空间复杂度:O(1),我们只使用了有限的额外空间。
总结
这个问题的关键在于理解如何通过一次遍历来确定所有可能的合法分割点。通过维护两个和 suml
和 sumr
,我们可以在不牺牲效率的情况下快速判断每个分割点的合法性。这种方法简单且高效,适用于处理此类问题。