当前位置: 首页 > article >正文

[算法初阶]第二集 滑动窗口(已完结)

大家好啊,好久没有更新了,最近比较忙,所以来更新初阶算法,正好复习一下,感谢大家的观看,如有错误欢迎指出。


下面我们来看题目吧!


1.209. 长度最小的子数组

这题大家想必一眼就看出了解法一暴力法

这个解法很简单

代码如下,不做多的解释

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) 
    {
        int n = nums.size();
        if (n == 0) 
        {
            return 0;
        }
        int ans = INT_MAX;
        for (int i = 0; i < n; i++) 
        {
            int sum = 0;
            for (int j = i; j < n; j++) 
            {
                sum += nums[j];
                if (sum >= s) 
                {
                    ans = min(ans, j - i + 1);
                    break;
                }
            }
        }
        return ans == INT_MAX ? 0 : ans;
    }
};

这个解法时间复杂度是O(n^{2})其中 n 是数组的长度。需要遍历每个下标作为子数组的开始下标,对于每个开始下标,需要遍历其后面的下标得到长度最小的子数组。

但是这不是我们要学的思路,我们要探究的是另一种的解法——滑动窗口

该解法思路:

定义两个指针 start 和 end 分别表示子数组(滑动窗口窗口)的开始位置和结束位置,维护变量 sum 存储子数组中的元素和(即从 nums[start] 到 nums[end] 的元素和)。

初始状态下,start 和 end 都指向下标 0,sum 的值为 0。

每一轮迭代,将 nums[end] 加到 sum,如果 sum≥s,则更新子数组的最小长度(此时子数组的长度是 end−start+1),然后将 nums[start] 从 sum 中减去并将 start 右移,直到 sum<s,在此过程中同样更新子数组的最小长度。在每一轮迭代的最后,将 end 右移。

代码如下

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) 
    {
        int n = nums.size();
        if (n == 0) 
        {
            return 0;
        }
        int ans = INT_MAX;
        int start = 0, end = 0;
        int sum = 0;
        while (end < n) 
        {
            sum += nums[end];
            while (sum >= s) 
            {
                ans = min(ans, end - start + 1);
                sum -= nums[start];
                start++;
            }
            end++;
        }
        return ans == INT_MAX ? 0 : ans;
    }
};

该方法时间复杂度:O(n)

2.3. 无重复字符的最长子串 - 力扣(LeetCode)

解法⼀(暴⼒求解,可以通过):
算法思路:
枚举「从每⼀个位置」开始往后,⽆重复字符的子串可以到达什么位置。找出其中⻓度最⼤的即
可。 在往后寻找⽆重复⼦串能到达的位置时,可以用「哈希表」统计出字符出现的频次
class Solution {
public:
 int lengthOfLongestSubstring(string s) {
 int ret = 0; // 记录结果
 int n = s.length();
 // 1. 枚举从不同位置开始的最⻓重复⼦串
 // 枚举起始位置
 for (int i = 0; i < n; i++)
 {
// 创建⼀个哈希表,统计频次
 int hash[128] = { 0 };
 
 // 寻找结束为⽌
 for (int j = i; j < n; j++)
 {
 hash[s[j]]++; // 统计字符出现的频次
 if (hash[s[j]] > 1) // 如果出现重复的
 break;
 
 // 如果没有重复,就更新 ret
 ret = max(ret, j - i + 1);
 }
 }
 // 2. 返回结果
 return ret;
 }
};

当然,我们知道我们想要的也不是这种解法

解法⼆(滑动窗口):
算法思路:
研究的对象依旧是⼀段连续的区间,因此继续使⽤「滑动窗口」思想来优化。
让滑动窗口满⾜:窗口内所有元素都是不重复的。
做法:右端元素 ch 进⼊窗口的时候,哈希表统计这个字符的频次:
  • 如果这个字符出现的频次超过 1 ,说明窗⼝内有重复元素,那么就从左侧开始划出窗口,直到 ch 这个元素的频次变为 1 ,然后再更新结果。
  • 如果没有超过 1 ,说明当前窗⼝没有重复元素,可以直接更新结果
    class Solution
    {
    public:
     int lengthOfLongestSubstring(string s) 
     {
     int hash[128] = { 0 }; // 使⽤数组来模拟哈希表
     int left = 0, right = 0, n = s.size();
     int ret = 0;
    while(right < n)
     {
     hash[s[right]]++; // 进⼊窗⼝
     while(hash[s[right]] > 1) // 判断
     hash[s[left++]]--; // 出窗⼝
     ret = max(ret, right - left + 1); // 更新结果
     right++; // 让下⼀个元素进⼊窗⼝
     }
     return ret;
     }
    };

    3.1004. 最大连续1的个数 III - 力扣(LeetCode)

思路与算法

不要去想怎么翻转,不要把问题想的很复杂,这道题的结果⽆⾮就是⼀段连续的 1 中间塞了 k
0 嘛。
因此,我们可以把问题转化成:求数组中⼀段最⻓的连续区间,要求这段区间内 0 的个数不超
k
代码如下
class Solution
{
public:
 int longestOnes(vector<int>& nums, int k) 
 {
 int 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;
 }
};

是不是很简单呢?


http://www.kler.cn/a/379358.html

相关文章:

  • 「Mac畅玩鸿蒙与硬件27」UI互动应用篇4 - 猫与灯的互动应用
  • Openlayers高级交互(18/20):根据feature,将图形适配到最可视化窗口
  • 解决 ClickHouse 高可用集群中 VRID 冲突问题:基于 chproxy 和 keepalived 的实践分析
  • dc源码铺子应用部署教程
  • GitHub每日最火火火项目(11.4)
  • 小张求职记四
  • 【NCRE】全国计算机一级必刷选择题(真题476道)
  • 第三十三章 Vue路由进阶路由模块封装
  • 【LeetCode:153. 寻找旋转排序数组中的最小值 + 二分】
  • sql将查到的所有id,拼接成字符串,用逗号隔开,并排序
  • 路由器中怎麼設置代理IP?
  • 微服务设计模式 - 发布订阅模式(Publisher Subscriber Pattern)
  • [java][高级]FilterListenerAjax
  • 同舟化工:实现LTC全流程数字化管控,赋能销售,提升运营效率
  • 基于springboot的Java学习论坛平台
  • 计算机系统架构
  • 【Python单元测试】pytest框架单元测试 配置 命令行操作 测试报告 覆盖率
  • Java项目管理与SSM框架介绍
  • 基于Multisim汽车尾灯电路左转右转刹车检查功能电路(含仿真和报告)
  • 一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?
  • 15分钟学 Go 第 33 天:项目结构
  • 【Git】如何在 Git 中高效合并分支:完整指南
  • 算法笔记()
  • 有效的数独(C语言解法)
  • Kubernetes中的cm存储
  • Docker入门系列——网络