目录
1、长度最小的子数组
题目链接https://leetcode.cn/problems/minimum-size-subarray-sum/description/
给定一个含有
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
解题思路:
1、我们首先想到的一定是暴力枚举所有的子数组,记录最小的长度即可解决问题。但这种解法必然超时。所以我们要对其进行优化。
2、当我们固定一端left,用right去枚举时,当right恰好走到大于等于target的位置。这时候right其实就没有必要继续往后走了,因为后面的长度都大于此时的长度!
3、那我们就更换固定点left,那这时候right也没有必要傻乎乎的回到固定点重新枚举。我们先让sum-=nums[left] ,left++(出窗口)。继续判断是否满足条件即可。
解题代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int len=nums.size();
int left=0,right=0,sum=0,ret=INT_MAX;
while(right<len)
{
//进窗口
sum+=nums[right];
while(left<len&&sum>=target)
{
//更新结果
ret=min(ret,right-left+1);
//出窗口
sum-=nums[left++];
}
right++;
}
return ret==INT_MAX?0:ret;
}
};
2、无重复字符的最长子串
给定一个字符串
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 len=s.size();
int hash[128]={0};
int ret=0;
for(int left=0,right=0;right<len;right++)
{
//进窗口
hash[s[right]]++;
//出窗口
while( hash[s[right]]>1)
{
hash[s[left]]--;
left++;
}
//更新结果
ret=max(ret,right-left+1);
}
return ret;
}
};
3、最大连续一的个数
题目链接https://leetcode.cn/problems/max-consecutive-ones-iii/description/
给定一个二进制数组
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 len=nums.size();
int ret=0;
for(int left=0,right=0;right<len;right++)
{
//进窗口
if(nums[right]==0) k--;
//出窗口
while(k<0)
{
if(nums[left]==0) k++;
left++;
}
//更新结果
ret=max(ret,right-left+1);
}
return ret;
}
};
4、将x见到0的最小操作数
题目链接https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/
给你一个整数数组
nums
和一个整数x
。每一次操作时,你应当移除数组nums
最左边或最右边的元素,然后从x
中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。如果可以将
x
恰好 减到0
,返回 最小操作数 ;否则,返回-1
。示例 1:
输入:nums = [1,1,4,2,3], x = 5 输出:2 解释:最佳解决方案是移除后两个元素,将 x 减到 0 。示例 2:
输入:nums = [5,6,7,8,9], x = 4 输出:-1示例 3:
输入:nums = [3,2,20,1,1,3], x = 10 输出:5 解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。
解题代码:
class Solution {
public:
int minOperations(vector<int>& nums, int x) {
int n=nums.size();
int ret=0,len=0,sum1=0,sum2=0;
//全部求元素之和
for(auto e:nums) sum1+=e;
if(sum1==x)
return n;
//求中间元素之和
int target=sum1-x;
for(int left=0,right=0;right<n;right++)
{
//进窗口
sum2+=nums[right];
//出窗口
while(left<n&&sum2>target) sum2-=nums[left++];
//更新结果
if(sum2==target) len=max(len,right-left+1);
}
//转换最小结果
return len==0?-1:n-len;
}
};
5、完结散花
好了,这期的分享到这里就结束了~
如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~
如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~
我们下期不见不散~~