本文主要是介绍[Algorithm][滑动窗口][无重复字符的最长字串][最大连续的一个数 Ⅲ][将x减到0的最小操作数]详细讲解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 1.无重复字符的最长字串
- 1.题目链接
- 2.算法原理详解
- 3.代码实现
- 2.最大连续的一个数 Ⅲ
- 1.题目链接
- 2.算法原理详解
- 3.代码实现
- 3.将x减到0的最小操作数
- 1.题目链接
- 2.算法原理详解
- 3.代码实现
1.无重复字符的最长字串
1.题目链接
- 无重复字符的最长字串
2.算法原理详解
- 研究的对象依旧是⼀段连续的区间,因此继续使⽤「滑动窗⼝」思想来优化
- 滑动窗口 + 哈希表(判断字符是否重复出现)
- 让滑动窗⼝满⾜:窗⼝内所有元素都是不重复的
- 做法:右端元素
s[right]
进⼊窗⼝的时候,哈希表统计这个字符的频次- 如果这个字符出现的频次超过1 ,说明窗⼝内有重复元素
- 那么就从左侧开始划出窗⼝, 直到
s[right]
这个元素的频次变为1,然后再更新结果
- 那么就从左侧开始划出窗⼝, 直到
- 如果没有超过1,说明当前窗⼝没有重复元素,可以直接更新结果
- 如果这个字符出现的频次超过1 ,说明窗⼝内有重复元素
3.代码实现
int LengthOfLongestSubstring(string s)
{int n = s.size(); int ret = 0;int hash[128] = { 0 }; // 利用hash查重for(int left = 0, right = 0; right < n; right++){hash[s[right]]++; // 入窗口while(hash[s[right]] > 1){hash[s[left++]]--; // 出窗口}ret = max(ret, right - left + 1); // 更新结果}return ret;
}
2.最大连续的一个数 Ⅲ
1.题目链接
- 最大连续的一个数 Ⅲ
2.算法原理详解
- 不要去想怎么翻转,不要把问题想的很复杂
- 这道题的结果⽆⾮就是⼀段连续的1中间塞了k个0
- 问题转化为:子数组内,0的个数不超过k
- 既然是连续区间,可以考虑使⽤**「滑动窗⼝」**来解决问题
- 做法:当
right < nums.size()
时,⼀直下列循环:- 让当前元素进⼊窗⼝
- 1 -> 无视
- 0 ->
zero++
- 检查0的个数是否超标
- 如果超标,依次让左侧元素滑出窗⼝
- 顺便更新
zero
的值,直到0的个数恢复正常
- 程序到这⾥,说明窗⼝内元素是符合要求的,更新结果
right++
,处理下⼀个元素
- 让当前元素进⼊窗⼝
3.代码实现
int LongestOnes(vector<int>& nums, int k)
{// 问题转化为,子数组内,0的个数不超过kint ret = 0;for(int left = 0, right = 0, zero = 0; right < nums.size(); right++){if(nums[right] == 0){zero++; // 入窗口}while(zero > k){if(nums[left++] == 0){zero--;}}ret = max(ret, right - left + 1);}return ret;
}
3.将x减到0的最小操作数
1.题目链接
- 将x减到0的最小操作数
2.算法原理详解
- 要求是数组「左端+右端」两段连续的、和为x的最短数组
- 可以转化成求数组内⼀段连续的、和为
sum(nums) - x
的最⻓数组- 即:将两端转化为中间连续
- 此时,就是熟悉的**「滑动窗⼝」**问题了
- 可以转化成求数组内⼀段连续的、和为
- 做法:
- 转化问题:求
target = sum(nums) - x
。- 如果
target < 0
,问题⽆解
- 如果
- 初始化左右指针
left = 0, right = 0
(滑动窗⼝区间表⽰为 [ l , r ) [l, r) [l,r)- 左右区间是否开闭很重要,必须设定与代码⼀致
- 记录当前滑动窗⼝内数组和的变量
sum = 0
- 记录当前满⾜条件数组的最⼤区间⻓度
len = -1
- 当
right < nums.size()
时,⼀直循环:if sum < target
right++
,直⾄sum >= target
,或right
已经移到头
if sum > target
left++
,直⾄sum <= target
,或left
已经移到头
- 如果经过前两步的左右移动使得
sum == target
- 维护满⾜条件数组的最⼤⻓度,并让下个元素进⼊窗⼝
- 维护满⾜条件数组的最⼤⻓度,并让下个元素进⼊窗⼝
- 转化问题:求
3.代码实现
int MinOperations(vector<int>& nums, int x)
{// 将模型转化为最长子数组的和 == (sumNum - x)int sum = 0, ret = -1;int target = -x;for(auto& e : nums){target += e;}// 细节处理,当target为负数时,怎么减都减不够if(target < 0){return -1;}for(int left = 0, right = 0; right < nums.size(); right++){sum += nums[right]; // 入窗口while(sum > target) // 判断{sum -= nums[left++]; // 出窗口}if(sum == target){ret = max(ret, right - left + 1); // 更新结果}}return ret == -1 ? -1 : nums.size() - ret;
}
这篇关于[Algorithm][滑动窗口][无重复字符的最长字串][最大连续的一个数 Ⅲ][将x减到0的最小操作数]详细讲解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!