[LeetCode] Minimum Size Subarray Sum

The problem statement has stated that there are both O(n) and O(nlogn) solutions to this problem. Let's see the O(n) solution first (taken from this link), which is pretty clever and short.

复制代码
 1 class Solution {
 2 public:
 3     int minSubArrayLen(int s, vector<int>& nums) {
 4         int start = 0, sum = 0, minlen = INT_MAX;
 5         for (int i = 0; i < (int)nums.size(); i++) {
 6             sum += nums[i];
 7             while (sum >= s) {
 8                 minlen = min(minlen, i - start + 1);
 9                 sum -= nums[start++];
10             }
11         }
12         return minlen == INT_MAX ? 0 : minlen;
13     }
14 };
复制代码

Well, you may wonder how can it be O(n) since it contains an inner while loop. Well, the key is that the while loop executes at most once for each starting position start. Then start is increased by 1 and the while loop moves to the next element. Thus the inner while loop runs at most O(n) times during the whole for loop from 0 to nums.size() - 1. Thus both the forloop and while loop has O(n) time complexity in total and the overall running time is O(n).

There is another O(n) solution in this link, which is easier to understand and prove it is O(n). I have rewritten it below.

复制代码
 1 class Solution {
 2 public:
 3     int minSubArrayLen(int s, vector<int>& nums) {
 4         int n = nums.size();
 5         int left = 0, right = 0, sum = 0, minlen = INT_MAX;
 6         while (right < n) {
 7             do sum += nums[right++];
 8             while (right < n && sum < s);
 9             while (left < right && sum - nums[left] >= s)
10                 sum -= nums[left++];
11             if (sum >= s) minlen = min(minlen, right - left);
12         }
13         return minlen == INT_MAX ? 0 : minlen;
14     }
15 };
复制代码

Now let's move on to the O(nlogn) solution. Well, this less efficient solution is far more difficult to come up with. The idea is to first maintain an array of accumulated summations of elements innums. Specifically, for nums = [2, 3, 1, 2, 4, 3] in the problem statement, sums = [0, 2, 5, 6, 8, 12, 15]. Then for each element in sums, if it is not less than s, we search for the first element that is greater than sums[i] - s (in fact, this is just what the upper_bound function does) in sumsusing binary search.

Let's do an example. Suppose we reach 12 in sums, which is greater than s = 7. We then search for the first element in sums that is greater than sums[i] - s = 12 - 7 = 5 and we find 6. Then we know that the elements in nums that correspond to 6, 8, 12 sum to a number 12 - 5 = 7 which is not less than s = 7. Let's check for that: 6 in sums corresponds to 1 in nums8 insums corresponds to 2 in nums12 in sums corresponds to 4 in nums1, 2, 4 sum to 7, which is 12 in sums minus 5 in sums.

We add a 0 in the first position of sums to account for cases like nums = [3], s = 3.

The code is as follows.

复制代码
 1 class Solution {
 2 public:
 3     int minSubArrayLen(int s, vector<int>& nums) {
 4         vector<int> sums = accumulate(nums);
 5         int minlen = INT_MAX;
 6         for (int i = 1; i <= nums.size(); i++) {
 7             if (sums[i] >= s) {
 8                 int p = upper_bound(sums, 0, i, sums[i] - s);
 9                 if (p != -1) minlen = min(minlen, i - p + 1);
10             }
11         }
12         return minlen == INT_MAX ? 0 : minlen;
13     }
14 private:
15     vector<int> accumulate(vector<int>& nums) {
16         vector<int> sums(nums.size() + 1, 0);
17         for (int i = 1; i <= nums.size(); i++)
18             sums[i] = nums[i - 1] + sums[i - 1];
19         return sums;
20     }
21     int upper_bound(vector<int>& sums, int left, int right, int target) {
22         int l = left, r = right;
23         while (l < r) {
24             int m = l + ((r - l) >> 1);
25             if (sums[m] <= target) l = m + 1;
26             else r = m;
27         }
28         if (sums[r] > target) return r;
29         if (sums[l] > target) return l;
30         return -1;
31     }
32 };
复制代码

 

posted @   jianchao-li  阅读(231)  评论(0编辑  收藏  举报
编辑推荐:
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
阅读排行:
· 从零开始开发一个 MCP Server!
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
点击右上角即可分享
微信分享提示