前言
空间换时间,利用前缀和快速获得一段子数组的和,或者抽象一段子数组,比如不一定全加,可以加减交替。
一、生成平衡数组的方案数
二、抽象前缀和
1、想法
直接想法:尝试删除每个元素,看奇偶位置上的值是否相等。
在此基础上换个角度:顺序访问,先加后减,知道末尾,看为0否?
新角度:联系上前缀和思想,遍历数组,不断更新以当前元素为中点,左右两段子数组的抽象前缀和,两者相减是否为0,即是否平衡。
2、Java
class Solution {
// 尝试删除每个元素,看奇偶位置上的值是否相等。
// 换个角度:顺序访问,先加后减,知道末尾,看为0否?
// 类前缀和,求得nums所有元素加减和,遍历数组,除去当前元素,是否平衡,再更新前段子数组和,后段子数组和。
public int waysToMakeFair(int[] nums) {
int sum = 0,step = 1;
// 后段子数组和。
for(int n : nums) {
sum += step * n;
step = -step;
}
int pre = 0;// 前段子数组和
step = 1;
int cnt = 0;
for(int i = 0;i < nums.length;i++){
sum -= step * nums[i];
// pre + (-sum) 少了一个就得变向,变加减的方向。
if(pre - sum == 0) cnt++;
pre += step * nums[i];
step = -step;
}
return cnt;
}
}
3、go
func waysToMakeFair(nums []int) int {
sum := getSum(nums)
pre,step,cnt := 0,1,0
for _,n := range nums {
sum -= step * n
if pre + (-sum) == 0 {
cnt++
}
pre += step * n
step = -step
}
return cnt
}
func getSum(nums []int) int {
sum,step := 0,1
for _,n := range nums {
sum += step * n
step = -step
}
return sum
}
总结
1)一个好的角度不是一下子来的,除法积累众多,否则需要从所谓的暴力慢慢分析过来。
2)抽象思维确实好用,像这里的抽象前缀和,同样空间换时间。