赞
踩
int func(vector<int> nums) { int left=0,right=0,var=0,ans=0,len=nums.size();//初始化left指针、right指针,再维护一个var变量,用来在指针移动过程中根据题意做出变化,再维护一个ans,也就是求的最小长度或者其他返回值 while (right<len) { //现在用nums[right]来更新var while (var满足条件) { //更新最优结果ans //用nums[left]来更新var //窗口缩小,即left指针右移 } right++; } return ans; }
核心思想是:当你移动right指针发现该子序列满足条件时,就会想要右移指针来贪心看看有没没有更短的符合条件的子序列
注意,维护的var变量不一定是一个变量,你也可以用集合,只要var能用来衡量是否满足子序列条件即可
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其和 ≥ target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度**。**如果不存在符合条件的子数组,返回 0
。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
代码如下:
class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int left=0,right=0,len=nums.size(),sum=0,ans=len+1; while (right<len) { sum+=nums[right];//维护sum while (sum>=target)//右移left指针缩小滑动窗口大小 { if (right-left+1<ans) ans=right-left+1;//更新最优结果 sum-=nums[left];//维护sum left++;//左指针右移 } right++; } if (ans==len+1) return 0;//有时候会有这样需要特殊判断的,假如本题完全没有符合条件的子序列,那么ans一定还是初始值,所以直接返回0 return ans; } };
解释:
int func(vector<int>& nums)
{
int left=0,right=0,var=0,len=nums.size(),ans=0;
while (right<len)
{
//用nums[right]更改var变量
while (var不满足条件)
{
//用nums[left]来更新var变量
left++;
}
if (xxxxxx) ;//更新最优结果ans
right++;
}
}
注意这里更新最优结果在while循环的外面,原因是因为while循环内其实都是不符合条件的子序列,所以无需更新最优结果
这里要注意的是while循环的条件变成了var不满足条件,因为此时的算法思想是:随着right指针右移,窗口越变越大,但如果窗口内的子序列不满足条件,就要右移left指针,直到条件重新符合
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
代码如下:
class Solution { public: int lengthOfLongestSubstring(string s) { int left=0,right=0,len=s.size(),ans=0; unordered_set<int> zifu;//注意这个其实就是var变量,用这个set来判断是否满足条件 while (right<len) { while (zifu.find(s[right])!=zifu.end())//发现此时有重复字符了 { zifu.erase(s[left]); left++; } if (right-left+1>ans) ans=right-left+1; zifu.insert(s[right]);//注意用right来改变变量时,可以在while循环后,这样可以避免一插入就认为不符合条件的情况 right++; } return ans; } };
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits
表示,其中 fruits[i]
是第 i
棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
给你一个整数数组 fruits
,返回你可以收集的水果的 最大 数目。
示例 1:
输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。
示例 2:
输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
示例 3:
输入:fruits = [1,2,3,2,2]
输出:4
解释:可以采摘 [2,3,2,2] 这四棵树。
如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。
示例 4:
输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。
代码:
class Solution { public: int totalFruit(vector<int>& fruits) { unordered_map<int,int> count; int left=0,right=0,ans=0,len=fruits.size(); while (right<len) { count[fruits[right]]++; while (count.size()>2) { if (count[fruits[left]]==1) count.erase(fruits[left]); else count[fruits[left]]--; left++; } if (right-left+1>ans) ans=right-left+1; right++; } return ans; } };
给定一个二进制数组 nums
和一个整数 k
,如果可以翻转最多 k
个 0
,则返回 数组中连续 1
的最大个数 。
示例 1:
输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:
输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。
代码:
class Solution { public: int longestOnes(vector<int>& nums, int k) { int left=0,right=0,len=nums.size(),ans=0,num=k; while (right<len) { while (nums[right]==0 && k==0) { if (nums[left]==0) k++; left++; } if (nums[right]==0 && k) k--; if (right-left+1>ans) ans=right-left+1; right++; } return ans; } };
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l
和 r
(l < r
)确定,如果对于每个 l <= i < r
,都有 nums[i] < nums[i + 1]
,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]]
就是连续递增子序列。
示例 1:
输入:nums = [1,3,5,4,7]
输出:3
解释:最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。
示例 2:
输入:nums = [2,2,2,2,2]
输出:1
解释:最长连续递增序列是 [2], 长度为1。
代码如下:
class Solution { public: int findLengthOfLCIS(vector<int>& nums) { int left=0,right=1,len=nums.size(),ans=-1; if (len<2) return 1; while (right<len) { while (nums[right]-nums[right-1]<=0 && left!=right) { left++; } if (right-left+1>ans) ans=right-left+1; right++; } return ans; } };
int func(vector<int>& nums)
{
int left=0,right=0,var=0,len=nums.size(),ans=0;
while (right<len)
{
//用nums[right]更改var变量
if ((right-left+1)==target_length) //窗口大小达到指定值
{
if (满足条件) xxxxxxx;
//用nums[left]来更新var变量
left++;
}
right++;
}
}
给你两个字符串 s1
和 s2
,写一个函数来判断 s2
是否包含 s1
的排列。如果是,返回 true
;否则,返回 false
。
换句话说,s1
的排列之一是 s2
的 子串 。
示例 1:
输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").
示例 2:
输入:s1= "ab" s2 = "eidboaoo"
输出:false
提示:
1 <= s1.length, s2.length <= 104
s1
和 s2
仅包含小写字母class Solution { public: bool checkInclusion(string s1, string s2) //s1是子串,s2是主串 { int left=0,right=0,len1=s1.size(),len2=s2.size(); vector<int> map1(26,0),map2(26,0);//用来记录串的字母组成 for (auto i:s1)//先将子串统计好,用于跟主串窗口做对比 { map1[i-'a']++; } //开始滑动窗口的主体 while (right<len2) { map2[s2[right]-'a']++;//窗口右移后,添加窗口中最后一位的字母 if ((right-left+1)==s1.size())//如果窗口长度达到目标值,判断窗口 { if (judge(map1,map2))//判断是否是子串的某一种排列 { return true; } map2[s2[left]-'a']--;//窗口右移,去除左边的字母 left++; } right++;//窗口右移 } return false; } bool judge(const vector<int>& map1,const vector<int>& map2)//判断字母组成是否相同 { for (int i=0;i<26;i++) { if (map1[i]!=map2[i]) return false; } return true; } };
【编程题】幼儿园有 N 个孩子玩游戏,随机围成了一个圈,老师最终想让所有男生排列到一起,所有女生排列到一起。每次老师可以命令两个孩子交换位置,求最小的命令次数:
N<=100
输入样例 1
3
FMF
输出样例 1
0
输入样例 2
4
FMFM
输出样例 2
1
int solution(int n, string s) { // 请添加具体实现 int cnt_f = 0, cnt_m = 0; for (int i = 0; i < s.size(); i++) { switch (s[i]) { case 'F': cnt_f++; break; case 'M': cnt_m++; break; }; } // cout << "cnt_f=" << cnt_f // << endl; int left = 0, right = 0, cnt_F = 0, cnt_M = 0; int target_len = cnt_f, min = INT_MAX; // cout << "target_len=" << target_len // << endl; while (left < n) { // cout << "left=" << left << " right=" << right << endl; if (s[right] == 'F') cnt_F++; // cout << "cnt_F=" << cnt_F << endl; if (((right + n - left + 1) % n) == target_len) { if (target_len - cnt_F < min) min = target_len - cnt_F; if (s[left] == 'F') cnt_F--; left++; } right++; if (right == n) right = 0; } return min; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。