作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址: https://leetcode.com/problems/minimum-size-subarray-sum/description/

题目描述:

Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn’t one, return 0 instead.

Example:

Input: s = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: the subarray [4,3] has the minimal length under the problem constraint.

Follow up:

  • If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).

题目大意

找出一个数组中最短连续的子数组,这个子数组的和要>=s.

解题方法

虫取法

碰巧今天在《挑战程序设计竞赛》一书中看到这个题,解法称之为虫取法,其实就是双指针。其实看到让连续子数组满足一定条件的很多都用了双指针,比如713. Subarray Product Less Than K

因为这个题需要求最小值,所以结果初始化为inf,每次移动一下右指针,当和满足条件的时候,更新结果,并移动左指针,同时记得把和删去左边的数字。这里求和的区间是左右都是闭区间。

时间复杂度是O(N),空间复杂度是O(1)。

class Solution:
def minSubArrayLen(self, s, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
N = len(nums)
l, r = 0, 0
csum = 0
res = float('inf')
while r < N:
csum += nums[r]
while csum >= s:
res = min(res, r - l + 1)
csum -= nums[l]
l += 1
r += 1
return res if res != float('inf') else 0

二刷的时候使用了C++,我同样选择了虫取法,但是对虫取法没有100%的信心,因为很多题目虫取法可能漏掉了解,而不容易发现。还好这个题目只有正整数,比较容易找到移动左右指针的规律,所以虫取法没什么问题。

我定义了两个指针left和right,定义了sum = [left…right)的和,其中区间是左闭右开,这样,right终止条件是right <=N,而满足题目要求的区间的长度是right - left。把这些弄明白之后就很容易写出代码了。

C++代码如下:

class Solution {
public:
// O(N) using two pointer
int minSubArrayLen(int s, vector<int>& nums) {
const int N = nums.size();
if (N == 0) return 0;
int left = 0, right = 0;
// sum = sum[left, right)
long long sum = 0;
int res = INT_MAX;
while (right <= N) {
if (sum >= s) {
res = min(res, right - left);
sum -= nums[left++];
} else {
sum += nums[right++];
}
}
return res == INT_MAX ? 0 : res;
}
};

二分查找

这个题有个follow up,让我们用o(NlogN)的时间复杂度去求解,很明显地,在考察我们二分。

思路很显然,对于每个位置求数组累积和,然后对于累积和的每个位置,去查找sums[i] - pos的位置在sums中的哪里。这样的话,就得到了一个区间,这个区间的累积和是不小于s的,即为题目所求。

这个题我写的二分是查找第一个不小于某个数字的位置,即lower_bound,这样会造成,当要查找的target不在sums中时,返回的结果是它右边的第一个数字。所以需要做个判断,如果查到了,那么区间长度是i - pos,否则区间长度应该+1.

class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
const int N = nums.size();
vector<int> sums;
sums.push_back(0);
for (int i = 0; i < N; ++i) {
sums.push_back(nums[i] + sums.back());
}
int res = INT_MAX;
for (int i = 1; i <= N; ++i) {
int target = sums[i] - s;
if (target < 0) continue;
auto pos = binary_search(sums, target);
if (pos > N) continue;
if (sums[i] - sums[pos] == s)
res = min(res, i - pos);
else if (sums[i] - sums[pos] < s)
res = min(res, i - pos + 1);
}
return res == INT_MAX ? 0 : res;
}
int binary_search(vector<int>& sums, int target) {
const int N = sums.size();
// [l, r)
int l = 0, r = N;
while (l < r) {
int mid = l + (r - l) / 2;
if (sums[mid] >= target) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
};

参考资料:

日期

2018 年 10 月 15 日 —— 美好的周一怎么会出现雾霾呢?
2019 年 1 月 11 日 —— 小光棍节?

【LeetCode】209. Minimum Size Subarray Sum 解题报告(Python & C++)的更多相关文章

  1. [LeetCode] 209. Minimum Size Subarray Sum 最短子数组之和

    Given an array of n positive integers and a positive integer s, find the minimal length of a contigu ...

  2. LeetCode 209. Minimum Size Subarray Sum (最短子数组之和)

    Given an array of n positive integers and a positive integer s, find the minimal length of a contigu ...

  3. LeetCode 209 Minimum Size Subarray Sum

    Problem: Given an array of n positive integers and a positive integer s, find the minimal length of ...

  4. Java for LeetCode 209 Minimum Size Subarray Sum

    Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...

  5. [LeetCode] Minimum Size Subarray Sum 解题思路

    Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...

  6. 【刷题-LeetCode】209. Minimum Size Subarray Sum

    Minimum Size Subarray Sum Given an array of n positive integers and a positive integer s, find the m ...

  7. LeetCode OJ 209. Minimum Size Subarray Sum

    Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...

  8. 【leetcode】Minimum Size Subarray Sum(middle)

    Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...

  9. 209. Minimum Size Subarray Sum(双指针)

    Given an array of n positive integers and a positive integer s, find the minimal length of a contigu ...

随机推荐

  1. 【蛋白质基因组】Proteogenomics方法介绍及分析思路

    概念 利用蛋白质组学数据,结合基因组数据(DNA).转录组数据(RNA)来研究基因组注释问题,被称为蛋白质基因组学."蛋白质基因组学"一词由Jaffe 等于2004 年首次提出,作 ...

  2. Django创建多对多表关系的三种方式

    方式一:全自动(不推荐) 优点:django orm会自动创建第三张表 缺点:只会创建两个表的关系字段,不会再额外添加字段,可扩展性差 class Book(models.Model): # ... ...

  3. Spring DAO

    Spring DAO 连接池 使用JDBC访问数据库是,频繁的打开连接和关闭连接,造成性能影响,所以有了连接池.数据库连接池负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接, ...

  4. 13 — springboot集成mybatis-plus — 更新完毕

    1.mybatis-plus需要掌握的知识 1).mybatis-plus是什么? 不写了,老衲一般都是直接进官网 mybatis-plus官网地址:https://baomidou.com/guid ...

  5. IDEA修改数据库信息,结果修改信息中文成 ?

    今天在用IDEA进行插入数据库信息时,发生了一件意想不到的事情,特意记录一下,方便后续查看: 就是我在IDEA的驱动文件中配置了useUnicode = true & characterEnc ...

  6. 振鹏学习Java的第二天!

    一.今日收获 1.了解了eclipse的具体使用方法. 2.学习了Java程序设计完全手册的第一章内容,明白了相关知识. 3.通过看哔哩哔哩的java的教程视频了解了Dos命令及java的变量和常量. ...

  7. A Child's History of England.24

    Besides all these troubles, William the Conqueror was troubled by quarrels among his sons. He had th ...

  8. Hive(六)【分区表、分桶表】

    目录 一.分区表 1.本质 2.创建分区表 3.加载数据到分区表 4.查看分区 5.增加分区 6.删除分区 7.二级分区 8.分区表和元数据对应得三种方式 9.动态分区 二.分桶表 1.创建分桶表 2 ...

  9. Oracle—merge into语法

    oracle的merge into语法,在这种情况下: 基于某些字段,存在就更新,不存在就插入: 不需要先去判断一下记录是否存在,直接使用merge into merge into 语法: MERGE ...

  10. oc中调用c函数 实现将字符串转换成unsigned char

    帮助码友解决问题,从而复习了一下oc中调用c函数的方式 1,新建c 头文件  test.h 定义 c 函数 #ifndef test_h #define test_h void verificatio ...