【练习】滑动窗口思想

news2024/11/24 6:03:13

  • 🎥 个人主页:Dikz12
  • 🔥个人专栏:Java算法
  • 📕格言:那些在暗处执拗生长的花,终有一日会馥郁传香
  • 欢迎大家👍点赞✍评论⭐收藏

目录

1.长度最小的子数组

题目解析 

讲解 

 代码实现

 2.无重复字符的最长子串

题目解析 

 讲解

代码实现 

3.最大连续1的个数 III

题目解析 

讲解 

代码实现 

4.将 x 减到 0 的最小操作数

题目解析

​编辑讲解 

代码实现 

 5.水果成篮

题目解析 

讲解 

代码实现 


1.长度最小的子数组

题目解析 

讲解 

解法一: 暴力枚举出所有子数组的和. O(n^2)

 

解法二:利用“滑动窗口”优化.(利用单调性,同向双指针) O(n)

  1. left = 0,right = 0
  2. 进窗口
  3. 判断
  4.  出窗口 或者 是更新结果

当sum 小于target时,就进窗口(right++);

满足判断条件(sum大于等于target)时,此时,更新结果,出窗口,可以⼤胆舍去 left得值然后left++,right也没有回退到left位置的必要了(left++)

 代码实现

    public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        int sum = 0, len = Integer.MAX_VALUE;
        for (int left = 0, right = 0; right < n; right++) {
            sum += nums[right];
            // 进窗口
            while (sum >= target) {
                // 更新len
                len = Math.min(len, (right - left + 1));
                // 出窗口
                sum -= nums[left++];
            }
        }
        return len == Integer.MAX_VALUE ? 0 : len;
    }

 2.无重复字符的最长子串

题目解析 

 讲解

解法一:暴力枚举 + 哈希表(判断字符是否重复出现)

枚举「从每⼀个位置」开始往后,⽆重复字符的⼦串可以到达什么位置。找出其中⻓度最⼤的即
可。在往后寻找⽆重复⼦串能到达的位置时,可以利⽤「哈希表」统计出字符出现的频次,来判断什么时候⼦串出现了重复元素.

解法二:使用“滑动窗口”来解决.

右端元素 ch 进⼊窗⼝的时候,使用数组模拟哈希来统计这个字符的频次:

  • 如果这个字符出现的频次超过1 ,说明窗⼝内有重复元素,那么就从左侧开始划出窗⼝,直到ch 这个元素的频次变为 1 ,然后再更新结果。
  • 如果没有超过1 ,说明当前窗⼝没有重复元素,可以直接更新结果

代码实现 

    public int lengthOfLongestSubstring(String s) {
        //转换成字符数组
        char[] ch = s.toCharArray();
        int ret =0,n = s.length();
        //利用ascii码值模拟
        int[] hash = new int[128];
        for(int left = 0,right = 0; right < n; right++) {
            hash[ch[right]]++;
            while(hash[ch[right]] > 1) { //判断
                 hash[ch[left++]]--;//出窗口
            }
            ret = Math.max(ret,right - left + 1);
        }
        return ret;

3.最大连续1的个数 III

题目解析 

讲解 

 意思就是:找出最长的子数组,且 0 的个数不能超过 k.

解法一: 暴力枚举 + 计数器(统计0出现的次数)

解法二:滑动窗口

  1. 定义left=0,right=0 ; count=0 统计0的次数;
  2.  进窗口,如果 等于 0,count++; 等于 1,不做处理
  3. 判断,当 count 大于 k,出窗口,出的时候,等于 0,count - -;等于 1,不做处理
  4. 更新结果. (不满足判断,直接更新结果;否则,先出窗口,在更新)

 

代码实现 

    public int longestOnes(int[] nums, int k) {
        int n = nums.length, count = 0, ret = 0;
        for (int left = 0, right = 0; right < n; right++) {
            if (nums[right] == 0) {
                count++;
            }
            while (count > k) { // 判断
                if (nums[left] == 0) {
                    count--;
                }
                left++; // 出窗口
            }
            ret = Math.max(ret, right - left + 1); // 更新结果
        }
        return ret;
    }

4.将 x 减到 0 的最小操作数

题目解析

讲解 

正难则反 :题⽬要求的是数组「左端+右端」两段连续的、和为 x 的最短数组. 转换成求数组内⼀段连续的、和为 sum(nums) - x 的最⻓数组.

 解法:滑动窗口. 

这是的写法就和第一题的时候就很相似了.(求等于target的最长的子数组) 

  1.  计算出 target = sum - x的值,target 小于 0,直接返回 -1;(sum为整个数组的和)
  2. 进窗口  right++(记录下当前和tmp)
  3. 判断. 当tmp大于target时,出窗口,先从tmp中舍去当前位置的值,在left++;
  4. 更新结果. 我们要的是 等于target 的子数组长度,需要加上个if条件.

代码实现 

    public int minOperations(int[] nums, int x) {
        int ret = -1,sum = 0,n = nums.length,tmp = 0;
        for(int i : nums) {
            sum += i;
        }
        int target = sum - x;
        if(target < 0) {
            return -1;
        }
        for(int left = 0,right = 0; right < n;right++) {
            //进窗口
            tmp += nums[right]; 
            //判断
            while(tmp > target) { 
              //出窗口
              tmp -= nums[left++];
            }
            if(tmp == target) {
                ret = Math.max(ret,right - left + 1);
            }
        }
        if(ret == -1) {
            return -1;
        }else{
            //ret是sum-x的长度
            return n - ret;
        }
    }

 5.水果成篮

题目解析 

 这么长的小作文,意思就是:找出一个最长的子数组的长度,子数组中不超过两种类型的水果.

讲解 

解法一:暴力枚举 + Map 容器. 

解法二:滑动窗口 .

 

指针同向移动,可以使用“滑动窗口.

  1.  初始化Map容器(也可以使用数组模拟),来统计窗⼝内⽔果的种类和数量;
  2. 初始化变量:左右指针 left = 0,right = 0,记录结果的变量 ret = 0
  3. 进窗口.将当前⽔果放⼊Map中;
  4. 判断.当前⽔果进来后,Map的⼤⼩:如果超过 2:将左侧元素滑出窗⼝,并且在Map中将该元素的value减⼀;如果这个元素的value减⼀之后变成了 0,就把该元素从哈希表中删除;
    重复上述两个过程,直到哈希表中的⼤⼩不超过 2;
  5.  更新结果

代码实现 

    public int totalFruit(int[] fruits) {
        int n = fruits.length, ret = 0;
        Map<Integer, Integer> map = new HashMap<>();
        for (int left = 0, right = 0; right < n; right++) {
            int key = fruits[right];
            map.put(key, map.getOrDefault(key, 0) + 1);// 进窗口
            // 判断
            while (map.size() > 2) {
                // 出窗口
                int out = fruits[left];
                map.put(out, map.get(out) - 1);
                if (map.get(out) == 0) {
                    map.remove(out);
                }
                left++;
            }
            ret = Math.max(ret, right - left + 1);
        }
        return ret;
    }

 数组模拟实现:

   public int totalFruit(int[] fruits) {
        int n = fruits.length, ret = 0;
        int[] map = new int[n+1];
        // Map<Integer, Integer> map = new HashMap<>();
        for (int left = 0, right = 0,type = 0; right < n; right++) {
            int key = fruits[right];
            // map.put(key, map.getOrDefault(key, 0) + 1);// 进窗口
            if(map[key] == 0) {
                type++; //记录水果种类
            }
            map[key]++; //进窗口
            // 判断
            while (type > 2) {
                // 出窗口
                int out = fruits[left];
                map[out]--;
                // map.put(out, map.get(out) - 1);
                if (map[out] == 0) {
                    type--;
                }
                left++;
            }
            ret = Math.max(ret, right - left + 1);
        }
        return ret;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1559640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序(黑马优购:登录)

1.点击结算进行条件判断 user.js //数据 state: () >({ // address: {} address: JSON.parse(uni.getStorageSync(address) || {}), token: }), my-settle.vue computed: { ...mapGetters(m_cart,[checkedCount,total,checkedGoodsAmount]), …

MySQL经验分享:Shell开发问题

背景 之前整理过Python连接使用MySQL的经验&#xff0c;链接如下&#xff1a; pymysql封装总结_pymysql封装类-CSDN博客 相比高级语言&#xff0c;Shell与MySQL开发使用相对会更麻烦一些&#xff1b;由于 shell是linux命令集的概称&#xff0c;是属于命令行的人机界面。Shel…

机器视觉学习(八)—— 阈值化

目录 一、阈值化 二、二值化和示例 2.1 二值化 2.2 示例代码 一、阈值化 OpenCV是一个开源的计算机视觉库&#xff0c;可以用于图像处理和计算机视觉任务。阈值化是图像处理中的一种常见操作&#xff0c;可以将图像的像素值分成两个或多个不同的类别&#xff0c;通常是黑色…

python统计分析——双样本均值比较

参考资料&#xff1a;python统计分析【托马斯】 1、配对样本t检验 在进行两组数据之间的比较时&#xff0c;有两种情况必须区分开。在第一种情况中&#xff0c;同一对象在不同时候的两个记录值进行相互比较。例如&#xff0c;用学生们进入初中时的身高和他们一年后的身高&…

wails 创建Go 项目

##wails是一个可以让go和web技术编写桌面应用#安装wails go install github.com/wailsapp/wails/v2/cmd/wailslatest#检查环境 wails doctor 创建项目wails init -n AuxiliaryTools -t vue-ts拉取go.mod的依赖项 go mod tidy进入 frontend 前端安装依赖项npm install /pnpm ins…

GitHub - 使用SSH进行连接(续)

文章目录 前言开发环境SSH源码获取SSH源码分析最后 前言 上篇文章中提出了存在一些默认密钥文件会被SSH自动添加的猜测&#xff0c;现在我们通过一些分析来验证这个猜测。 开发环境 MacOS: 14.3.1SSH: OpenSSH_9.4p1 SSH源码获取 该怎么验证这个猜测呢&#xff1f;有个方法…

QT初识(2)

QT初识&#xff08;2&#xff09; 创建好项目之后&#xff0c;多了些什么东西&#xff1f;main.cppwidget.hwidget.cppwidget.ui.pro项目工程文件 我们今天来继续了解QT。如果没看过上一次QT初识的小伙伴可以点击这里&#xff1a; https://blog.csdn.net/qq_67693066/article/d…

ADB(Android Debug Bridge)操作命令详解及示例

ADB&#xff08;Android Debug Bridge&#xff09;是一个强大的命令行工具&#xff0c;它是Android SDK的一部分&#xff0c;主要用于Android设备&#xff08;包括真实手机和平板电脑以及模拟器&#xff09;的调试、系统控制和应用程序部署。 下面是一些ADB的常用命令&#xff…

全国植被覆盖度VFC逐月数据/NDVI/净初级生产力NPP/植被类型​

引言 植被覆盖度是指植被&#xff08;包括叶、茎、枝&#xff09;在地面的垂直投影面积占统计区总面积的百分比。是刻画地表植被覆盖的一个重要参数, 也是指示生态环境变化的重要指标之一。 正文 数据简介 容易与植被覆盖度混淆的概念是植被盖度&#xff0c;植被盖度是指植被冠…

腾讯云轻量服务器8核16G服务器价格1668元一年送3个月,18M大带宽

腾讯云轻量应用服务器8核16G配置租用优惠价格1668元15个月&#xff0c;买一年送3个月&#xff0c;配置为&#xff1a;轻量8核16G18M、270GB SSD盘、3500GB月流量、18M带宽&#xff0c;腾讯云优惠活动 yunfuwuqiba.com/go/txy 活动链接打开如下图&#xff1a; 腾讯云8核16G服务器…

复写零->C语言和JAVA版本的双指针解法

使用C语言和JAVA语言版本双指针来解决复写零问题 力扣链接:https://leetcode.cn/problems/duplicate-zeros/description/ 题意:对一个数组进行复写,遇到0写两遍,非0写一遍,复写结果不能超过原数组长度,即当复写结果达到数组长度时,后面的结果数组元素直接舍弃. 例子 思路:找到…

Spring Boot单元测试全指南:使用Mockito和AssertJ

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

机器学习每周挑战——旅游景点数据分析

数据的截图&#xff0c;数据的说明&#xff1a; # 字段 数据类型 # 城市 string # 名称 string # 星级 string # 评分 float # 价格 float # 销量 int # 省/市/区 string # 坐标 string # 简介 string # 是否免费 bool # 具体地址 string拿到数据…

SAP 学习笔记 - 系统移行业务 - Migration cockpit工具 - 移行Material(品目)

本章开始&#xff0c;来研究研究移行工具 Migration cockpit。 理论啥的先放一边&#xff0c;来先做一个简单的实例&#xff0c;以对 Migration cockpit 有个大概的印象。 这里就先做一个移行品目的例子。 1&#xff0c;LTMC 启动Migration cockpit工具 默认给我启动了 IE &a…

Python基础之pandas:Series和DataFrame定义及使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Series特点二、Series使用步骤1.Series定义2.索引和切片3.series的.get()4.掩码提取5.Series运算符和广播方法6.ufunc在Series对象中使用 三、DataFrame1.D…

使用python实现i茅台自动预约

使用python实现i茅台自动预约[仅限于学习&#xff0c;不可商用] 运行&#xff1a; 直接运行 imtApi.py 打包&#xff1a;切换到imt脚本目录&#xff0c;执行打包命令&#xff1a; pyinstaller --onefile imtApi.py这个应用程序可以帮助你进行茅台自动化配置。以下是一些使用…

【Laravel】06 数据库迁移工具migration

【Laravel】06 数据库迁移工具migration 1.migration文件目录2. 举例 1.migration文件目录 2. 举例 (base) ➜ example-app php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_crea…

Java基础学习: JDK动态代理

文章目录 一、什么是JDK动态代理二、JDK动态代理的特点三、JDK动态代理类如何使用四、JDK动态代理原理分析1、创建代理对象2、生成代理类 一、什么是JDK动态代理 JDK动态代理是Java提供的一种动态生成代理类和代理对象的技术。它主要利用Java的反射机制实现&#xff0c;在运行…

算法学习——LeetCode力扣动态规划篇10(583. 两个字符串的删除操作、72. 编辑距离、647. 回文子串、516. 最长回文子序列)

算法学习——LeetCode力扣动态规划篇10 583. 两个字符串的删除操作 583. 两个字符串的删除操作 - 力扣&#xff08;LeetCode&#xff09; 描述 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个…

2010-2021年各省碳排放测算数据(含原始数据+计算过程+结果)

2010-2021年各省碳排放测算数据&#xff08;含原始数据计算过程结果&#xff09; 1、时间&#xff1a;2010-2021年 2、指标&#xff1a;原煤(万吨)、原煤(万吨CO2)、焦炭(万吨)、焦炭(万吨CO2)、汽油(万吨)、汽油(万吨CO2)、煤油(万吨)、煤油(万吨CO2)、柴油(万吨)、柴油(万吨…