给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度**。**如果不存在符合条件的子数组,返回 0
二分:
因为数据都是大于0的,因此数组的前缀和数组是单调增的,
我们遍历每一个元素,二分去小最小的满足s[r]-s[l-1]>=target
的位置即可。
时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
或者 :滑动窗口
维护一个变量sum
,记录区间的和
两个指针l,r
指向区间的尾巴和头部,每次迭代,将nums[r]
加入到sum
中,
sum>=target
了,更新res
,并且指针l
右移,直到不满足sum>=target
二分:
int minSubArrayLen(int target, vector<int>& nums) {
int res=1e6;
int n=nums.size();
vector<int> s(n+10);
for(int i=1;i<=n;i++) s[i]=s[i-1]+nums[i-1];
for(int i=1;i<=n;i++){
int l=i,r=n;
while(l<r){
int m=(l+r)>>1;
if(s[m]-s[i-1]>=target) r=m;
else l=m+1;
}
if(s[l]-s[i-1]>=target){
res=min(res,l-i+1);
}
}
if(res==1e6) res=0;
return res;
}
滑动窗口:
int minSubArrayLen(int target, vector<int>& nums) {
int res=1e6;
int l=0,r=0;
int sum=0;
int n=nums.size();
for(;r<n;r++){
sum+=nums[r];
while(sum>=target) res=min(res,r-l+1),sum-=nums[l++];
}
if(res==1e6) res=0;
return res;
}
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits
表示,其中 fruits[i]
是第 i
棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
给你一个整数数组 fruits
,返回你可以收集的水果的 最大 数目。
滑动窗口:
定义两个指针:指向区间的开始和结尾
开一个哈希表来记录区间内每个元素出现的次数,
如果哈希表的长度大于2了,那么就从左边开始删
注意当哈希表内没有这个元素的时候,需要删除key
int totalFruit(vector<int> &fruits) {
int n = fruits.size();
map<int, int> mp;
int l = 0, res = 0;
for (int r = 0; r < n; r++) {
mp[fruits[r]]++;
while (mp.size() > 2) {
auto it= mp.find(fruits[l]);
it->second--;
if (mp[fruits[l]] == 0) mp.erase(it);
l++;
}
res = max(res, r - l + 1);
}
return res;
}
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
滑动窗口:
开两个哈希表,tt记录t中每个字符出现的次数,ss记录窗口中每个字符出现的次数
遍历字符串的右端点,每次去check是不是满足tt的字符包含于ss的字符个数。
如果满足,那么就可以不断缩小左端点,更新答案
时间复杂度为 O ( 26 n ) O(26n) O(26n)
string minWindow(string s, string t) {
int n = s.size();
map<int, int> tt, ss;
for (char c: t) tt[c]++;
int len = 1e6, ansL = -1;
int l = 0, r = -1;
auto check = [&]() -> bool {
for (auto [x, y]: tt) {
if (ss[x] < y) return false;
}
return true;
};
while (r < n) {
if (tt.find(s[++r]) != tt.end()) ss[s[r]]++;
while (check() && l <= r) {
if (r - l + 1 < len) {
len = r - l + 1;
ansL = l;
}
if (tt.find(s[l]) != tt.end()) ss[s[l]]--;
l++;
}
}
string res = "";
if (ansL != -1) res = s.substr(ansL, len);
return res;
}
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
按照题目模拟即可
vector<vector<int>> generateMatrix(int n) {
int l=0,r=n-1,b=n-1,t=0;
vector<vector<int>> res(n,vector<int>(n));
int num=1,tar=n*n;
while(num<=tar){
for(int i=l;i<=r;i++) res[t][i]=num++;
t++;
for(int i=t;i<=b;i++) res[i][r]=num++;
r--;
for(int i=r;i>=l;i--) res[b][i]=num++;
b--;
for(int i=b;i>=t;i--) res[i][l]=num++;
l++;
}
return res;
}
给你一个 m
行 n
列的矩阵 matrix
,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
模拟。
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int n=matrix.size(),m=matrix[0].size();
vector<int> res;
int l=0,r=m-1,t=0,b=n-1;
int sum=n*m;
while(sum){
for(int i=l;i<=r;i++) res.push_back(matrix[t][i]),sum--;
if(++t>b) break;
for(int i=t;i<=b;i++) res.push_back(matrix[i][r]),sum--;
if(--r<l) break;
for(int i=r;i>=l;i--) res.push_back(matrix[b][i]),sum--;
if(--b<t) break;
for(int i=b;i>=t;i--) res.push_back(matrix[i][l]),sum--;
if(++l>r) break;
}
return res;
}
给定一个二维数组 array
,请返回「螺旋遍历」该数组的结果。
螺旋遍历:从左上角开始,按照 向右、向下、向左、向上 的顺序 依次 提取元素,然后再进入内部一层重复相同的步骤,直到提取完所有元素。
示例 1:
输入:array = [[1,2,3],[8,9,4],[7,6,5]]
输出:[1,2,3,4,5,6,7,8,9]
示例 2:
输入:array = [[1,2,3,4],[12,13,14,5],[11,16,15,6],[10,9,8,7]]
输出:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
模拟
vector<int> spiralArray(vector<vector<int>>& a) {
vector<int> res;
if(a.empty()) return res;
int n=a.size(),m=a[0].size();
int l=0,t=0,r=m-1,b=n-1;
while(1){
for(int i=l;i<=r;i++) res.push_back(a[t][i]);
if(++t>b) break;
for(int i=t;i<=b;i++) res.push_back(a[i][r]);
if(--r<l) break;
for(int i=r;i>=l;i--) res.push_back(a[b][i]);
if(--b<t) break;
for(int i=b;i>=t;i--) res.push_back(a[i][l]);
if(++l>r) break;
}
return res;
}