[LeetCode] Minimum Size Subarray Sum

本文探讨了子数组和问题的两种解决方案:一种为O(n)复杂度的算法,通过巧妙的内循环避免冗余计算;另一种为O(nlogn)复杂度的算法,利用前缀和与二分查找加速搜索过程。通过实例解析,深入理解算法设计思想。

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 };

 

转载于:https://www.cnblogs.com/jcliBlogger/p/4600467.html

### LeetCode Top 100 Popular Problems LeetCode provides an extensive collection of algorithmic challenges designed to help developers prepare for technical interviews and enhance their problem-solving skills. The platform categorizes these problems based on popularity, difficulty level, and frequency asked during tech interviews. The following list represents a curated selection of the most frequently practiced 100 problems from LeetCode: #### Array & String Manipulation 1. Two Sum[^2] 2. Add Two Numbers (Linked List)[^2] 3. Longest Substring Without Repeating Characters #### Dynamic Programming 4. Climbing Stairs 5. Coin Change 6. House Robber #### Depth-First Search (DFS) / Breadth-First Search (BFS) 7. Binary Tree Level Order Traversal[^3] 8. Surrounded Regions 9. Number of Islands #### Backtracking 10. Combination Sum 11. Subsets 12. Permutations #### Greedy Algorithms 13. Jump Game 14. Gas Station 15. Task Scheduler #### Sliding Window Technique 16. Minimum Size Subarray Sum 17. Longest Repeating Character Replacement #### Bit Manipulation 18. Single Number[^1] 19. Maximum Product of Word Lengths 20. Reverse Bits This list continues up until reaching approximately 100 items covering various categories including but not limited to Trees, Graphs, Sorting, Searching, Math, Design Patterns, etc.. Each category contains multiple representative questions that cover fundamental concepts as well as advanced techniques required by leading technology companies when conducting software engineering candidate assessments. For those interested in improving logical thinking through gaming activities outside traditional study methods, certain types of video games have been shown beneficial effects similar to engaging directly within competitive coding platforms [^4]. --related questions-- 1. How does participating in online coding competitions benefit personal development? 2. What specific advantages do DFS/BFS algorithms offer compared to other traversal strategies? 3. Can you provide examples illustrating how bit manipulation improves performance efficiency? 4. In what ways might regular participation in programming contests influence job interview success rates? 5. Are there any notable differences between solving problems on paper versus implementing solutions programmatically?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值