编程-前缀和
560. 和为K的子数组
示例 1 :
输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
说明 :
- 数组的长度为 [1, 20,000]。
- 数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]。
hashmap-set
设S[i]为累加和,即S[i] = A[0] + A[1] + ... + A[i]。
现在要找出一个连续子数组,以A[i]结尾,且和为k。
那么,只要存在j < i,且S[j] == S[i] - k时就行了。
因此,只要用哈希表hash<S,{下标j}>,记录S的各个值即可。如此就能快速找到S[j]了。
class Solution { public: int subarraySum(vector<int>& nums, int k) { unordered_map<int,set<int>> hash; int s = 0; hash[0].insert(-1); int ans = 0; for(int i=0;i<nums.size();++i){ s += nums[i]; int t = s - k; if(hash.count(t)){ ans += hash[t].size(); } hash[s].insert(i); } return ans; } };
修改hashmap
class Solution { public: int subarraySum(vector<int>& nums, int k) { unordered_map<int, int> hash; int s = 0; hash[0]=1; int ans = 0; for(int i=0;i<nums.size();++i){ s += nums[i]; int t = s - k; if(hash.count(t)){ ans += hash[t]; } hash[s]++; } return ans; } };
517. 超级洗衣机
在每一步操作中,你可以选择任意 m (1 ≤ m ≤ n) 台洗衣机,与此同时将每台洗衣机的一件衣服送到相邻的一台洗衣机。
给定一个非负整数数组代表从左至右每台洗衣机中的衣物数量,请给出能让所有洗衣机中剩下的衣物的数量相等的最少的操作步数。如果不能使每台洗衣机中衣物的数量相等,则返回 -1。
示例 1:
输入: [1,0,5] 输出: 3 解释: 第一步: 1 0 <-- 5 => 1 1 4 第二步: 1 <-- 1 <-- 4 => 2 1 3 第三步: 2 1 <-- 3 => 2 2 2
示例 2:
输入: [0,3,0] 输出: 2 解释: 第一步: 0 <-- 3 0 => 1 2 0 第二步: 1 2 --> 0 => 1 1 1
示例 3:
输入: [0,2,0] 输出: -1 解释: 不可能让所有三个洗衣机同时剩下相同数量的衣物。
提示:
- n 的范围是 [1, 10000]。
- 在每台超级洗衣机中,衣物数量的范围是 [0, 1e5]
解法详解
方法一:贪心
首先,显然只有当 N 台洗衣机的衣服数量之和 D 是 N 的倍数时,才能使得每台洗衣机最终的衣服数量相等。
当计算出 D 之后,我们可以通过 D / N 得到每台洗衣机最终的衣服数量。
为了方便计算,我们可以将所有的 N 个数分别减去 D / N,这样若第 i 台洗衣机对应的数为正数,说明它需要拿出衣服分给别的洗衣机;若第 i 台洗衣机对应的数为负数,说明它需要从别的洗衣机得到衣服。
由于每一步操作中一台洗衣机只能给出一件衣服,因此如果其中一台洗衣机对应的数为正数 x,那么操作步数至少为 x。并且对于前 i 台洗衣机,它们对应的数的和若为 y,那么它们需要和后 N - i 台洗衣机至少传递 |y| 次衣服,每次只能传递一件(若 y 为正数,则前者将衣服传递给后者;若 y 为负数,则后者将衣服传递给前者),操作步数至少为 y。因此,最少的操作步数为“数组元素的最大值”和“数组元素前缀和的绝对值的最大值”中的较大值。
我们从左到右扫描数组,并求出以下三个值:
m:当前位置的数值;
curr_sum:到当前位置为止的前缀和;
max_sum:到当前位置为止的前缀和的绝对值的最大值。
通过这三个值,我们就能求出最少的操作步数。下面给出了三个例子:
[1, 0, 5],“数组元素的最大值” 和 “数组元素前缀和的绝对值的最大值” 相等:
[0, 3, 0],“数组元素的最大值” 为较大值:
[0, 0, 3, 5],“数组元素前缀和的绝对值的最大值” 为较大值:

浙公网安备 33010602011771号