单调栈解决循环数组下一个更大元素问题
2026/10/26 11:11:24
前言
本专栏文章为《LeetCode 热题 100》的刷题题解,相关内容如有侵权,立即删除。
560.和为 K 的子数组
核心思路:前缀和+哈希表。
prefix_sum[i]为前i ii个元素的和(令prefix_sum[0] = 0)。任意连续子数组nums[j..i-1]的和可以表示为:sum ( j , i − 1 ) = prefix_sum [ i ] − prefix_sum [ j ] \text{sum}(j, i-1) = \text{prefix\_sum}[i] - \text{prefix\_sum}[j]sum(j,i−1)=prefix_sum[i]−prefix_sum[j]current_sum。current_sum - k,将其出现次数累加到答案中。current_sum记录到哈希表中(频次 +1)。关键边界条件
mp[0] = 1。这代表“前缀和为 0 出现过 1 次”,用来处理从下标 0 开始的子数组和恰好等于k kk的情况(即current_sum - k == 0)。复杂度分析
- 时间复杂度:O ( n ) O(n)O(n),只需单次遍历数组,哈希表单次存取平均时间为O ( 1 ) O(1)O(1)。
- 空间复杂度:O ( n ) O(n)O(n),哈希表最多存储O ( n ) O(n)O(n)个不同的前缀和。
classSolution{public:intsubarraySum(vector<int>&nums,intk){// 哈希表用于记录 前缀和 出现的频次unordered_map<int,int>prefix_freq;prefix_freq[0]=1;// 前缀和为 0 出现了 1次intcurrent_sum=0;// 记录遍历过程中累加前缀和intcount=0;// 记录符合条件的子数组总数for(intnum:nums){current_sum+=num;// 更新当前的前缀和// 查找前面是否存在 prefix_sum 使得 current_sum - prefix_sum = k// 每一个对应的查询历史上等于 (current_sum - k) 的位置到当前位置都能构成一个和为 k 的子数组if(prefix_freq.count(current_sum-k)){count+=prefix_freq[current_sum-k];// 2026.10.25重做后: 注意count不是++}// 将当前前缀和加入哈希表prefix_freq[current_sum]++;}returncount;}};前缀和(Prefix Sum)与哈希表(Hash Map)是解决连续子数组和问题的经典组合。其核心思想是将“子数组和”问题转化为“两数之差”问题,并利用哈希表实现O(1)时间的历史查询。
适用场景:
关键思想:
prefix[i]为前i个元素之和。任意子数组nums[j..i-1]的和可表示为prefix[i] - prefix[j]。prefix[i] - prefix[j] = k转化为寻找历史上是否存在prefix[j] = prefix[i] - k。遍历时,用哈希表记录每个前缀和出现的次数,即可在O(1)时间内得到以当前位置结尾的、和为k的子数组数量。{0: 1},以处理从数组开头开始的子数组(即prefix[i] - 0 = k)。相关 LeetCode 例题: