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

动态维护有效区间:滑动窗口

右指针不断移动获取解,左指针不断移动缩小解范围

左指针的意义非常重要,相当于一个标兵,不断与这个标兵进行比较,如果符合要求,这左指针进行移动,并进行操作,如果不符合要求,则左指针不动,右指针接着寻找符合要求的值。

删除有序数组中的重复项

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]

暴力解法

一种非常简单的办法就是创建一个新的数组,每次添加元素的时候判断是否已经添加过了

class Solution:def removeDuplicates(self, nums: List[int]) -> int:res = []for v in nums:if v in res:continueres.append(v)return res

但是要求我们原地删除重复的数组,不能创建新的数组。因为数组是有序的,相同的元素已经排在了一起,如果前后两个元素不同,那么我们就找到了一个新的元素。

滑动窗口

我么定义两个指针lr,右指针不断往后遍历找到与左指针不同的元素,找到以后左指针也往后走一步,然后进行交换

1. 初始化左指针和右指针

00001123
l,r

2. 右指针不断遍历找到不同的元素

00001123
lr

3. 左指针移动一位,准备放入下一个不同元素

00001123
lr

4. 把当前不同的元素放到前面

01001123
lr

5. 重复之前的逻辑

右指针不断移动找下一个不同的元素

01001123
lr

找到后左指针移动并填充

01201123
lr

右指针不断移动找下一个不同的元素

01001123
lr

找到后左指针移动并填充

01231123
lr

6.右指针到底末端结束

class Solution:def removeDuplicates(self, nums: List[int]) -> int:l = 0for r in range(len(nums)):if nums[l] != nums[r]:l += 1nums[l] = nums[r]return l+1

在这个问题中,我们可以破坏数组,所以可以直接将后面的元素覆盖到前面去

删除有序数组中的重复项 II

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

暴力解法

我们定义一个数组,不断添加元素,如果与这个数组尾端不同,则直接添加进来,如果与尾端相同,我们则判断添加的次数,超过2之后不在添加

class Solution:def removeDuplicates(self, nums: List[int]) -> int:tmp = []k = 1for i in range(len(nums)):# 如果为空则直接添加# 如果与末端元素不同也直接添加if not tmp or tmp[-1] != nums[i]:tmp.append(nums[i])k = 1# 如果与末端元素相同,则记录添加的次数k += 1# 小于2次则接着添加if k <= 2:tmp.append(nums[i])return tmp           

一个小小的优化是,其实我们不需要记录重复的次数,由于末端我们只会2个相同的元素,因此只需要比较tmp[-2]是否相同即可

temp[-3]temp[-2]temp[-1]nums[i]
前两个相同xxynums[i]!=tmpe[-2],说明中间只有一个y,可以直接添加
后两个相同xyy如果nums[i]==temp[-2],说明中间已经有一个y了,不能再添加了
全都不同xzynums[i]!=tmpe[-2],说明中间只有一个y,可以直接添加
class Solution:def removeDuplicates(self, nums: List[int]) -> int:if len(nums) <= 2:return numstmp = [nums[0],nums[1]]for i in range(2, len(nums)):# 如果为空则直接添加# 如果nums[i] != tmp[-2]说明末端元素只有一个,无脑添加if not tmp or tmp[-2] != nums[i]:tmp.append(nums[i])return tmp    

滑动窗口

数组是有序的,因此所有相同的元素肯定都是在一起出现的,同时要求一个元素最多出现两次,一个简单的想法就是
右指针不断移动,直到找到与左指针不同的元素,我们要把这个不同元素保留下来,即直接放到前面去(当前左指针后面)

000011123
lr

放到前面去

010011123
lr

由于重复元素需要保留2个,左指针需要再移动一位存放元素

010011123
lr

把重复的第2个值保留到前面

011011123
lr

当前这个元素已经满足要求了(不超过2个),右指针接着往后找下个不同的元素

011011123
lr

我们需要记录当前元素已经找到几个相同的了,如果小于等于2,那么左指针都需要跟着走,如果大于2了,左指针就不要动了,一直等找到下一个不同的元素

理清思路

好好理一下思路

  1. 右指针不断后移找到不同的元素
  2. 定义一个变量,记录当前的元素重复的次数
  3. 如果小于等于k,那么左指针移动,并将这个元素保留过来
  4. 如果重复次数超过了k,左指针不动,一直找到下一个重复元素,k重新赋值为1
class Solution:def removeDuplicates(self, nums: List[int]) -> int:if not nums:  # 处理空数组return 0l = 0k = 1  # nums[l] 初始出现1次# r从1开始,因为0位置已被l标记for r in range(1, len(nums)):if nums[l] == nums[r]:k += 1# 出现次数<=2时,扩展有效数组if k <= 2:l += 1nums[l] = nums[r]  # 这里漏了赋值,需要补充else:# 遇到新元素,重置计数并扩展有效数组k = 1l += 1nums[l] = nums[r]return l + 1

滑动窗口优化

因为数组是有序的,重复元素会连续排列。假设有效数组的最后两个元素是nums[l-2]和nums[l-1](当l >= 2时),此时:

  • 如果num == nums[l-2],说明nums[l-2]、nums[l-1]、num三者相等(因为数组有序,中间的nums[l-1]必然也等于num),加入num就会导致该元素出现 3 次,不符合要求。
  • 如果num != nums[l-2],说明即使num和nums[l-1]相等(最多出现 2 次),也不会超过限制,因此可以加入有效数组。
from typing import Listclass Solution:def removeDuplicates(self, nums: List[int]) -> int:l = 0  # 慢指针:指向有效数组的末尾for num in nums:# 核心判断:# 1. 有效数组长度不足2时,直接加入(前两个元素一定有效)# 2. 超过2个元素时,若当前元素与有效数组倒数第二个不同,说明可加入(避免3次重复)if l < 2 or num != nums[l-2]:nums[l] = numl += 1return l

文章转载自:

http://PWhEXT4l.fqymm.cn
http://3TIXVRSH.fqymm.cn
http://Ty2jIDqe.fqymm.cn
http://FPjOqiP8.fqymm.cn
http://XQaz80f0.fqymm.cn
http://6n4cfuOu.fqymm.cn
http://a4kuPMmP.fqymm.cn
http://UkcaAaFm.fqymm.cn
http://Mlk0uVpu.fqymm.cn
http://rvX8zA49.fqymm.cn
http://bQ0anW88.fqymm.cn
http://66WjaSgL.fqymm.cn
http://vxU2USrU.fqymm.cn
http://e3m9LUfJ.fqymm.cn
http://27k39kfo.fqymm.cn
http://SgTsc0Qa.fqymm.cn
http://BPPo8Zf3.fqymm.cn
http://Eluy1oVB.fqymm.cn
http://BI99J6J2.fqymm.cn
http://Qyk65LvX.fqymm.cn
http://3LHZe4LI.fqymm.cn
http://RuimOIn0.fqymm.cn
http://7ul48cUV.fqymm.cn
http://RXhEIzUu.fqymm.cn
http://zdekQBky.fqymm.cn
http://kEnkw7KH.fqymm.cn
http://RVO4ybvQ.fqymm.cn
http://z7RumjW1.fqymm.cn
http://pmfTWhPJ.fqymm.cn
http://ua1dLwur.fqymm.cn
http://www.dtcms.com/a/371318.html

相关文章:

  • 桌面时间 Catime
  • 解锁服务器网络配置新姿势:Wisdom SSH 助力之旅
  • 设计模式:状态模式(State Pattern)
  • 【ARM基础知道】
  • SpringCloud Alibaba微服务--Gateway使用
  • 基于脚手架微服务的视频点播系统-播放控制部分
  • 【C++详解】C++ 智能指针:使用场景、实现原理与内存泄漏防治
  • 【iOS】push,pop和present,dismiss
  • HiCMAE 论文复现:基于 RAVDESS 数据集的音视频情感识别
  • axios的两种异步方式对比
  • uniapp结合uview制作美食页面
  • Spark mapreduce 的一个用法
  • [iOS] push 和 present Controller 的区别
  • 五.贪心算法
  • vue中axios与fetch比较
  • 【iOS】block复习
  • 打造第二大脑读书笔记目录
  • 【Docker】Docker基础
  • 一、CMake基础
  • 【音视频】WebRTC P2P、SFU 和 MCU 架构
  • VBA 自动转化sheet到csv文件
  • rabbitmq 重试机制
  • 《C++进阶之STL》【set/map 使用介绍】
  • 【RabbitMQ】----初识 RabbitMQ
  • WebRTC开启实时通信新时代
  • JVM-默背版
  • Java内存区域与内存溢出
  • Python3使用Flask开发Web项目新手入门开发文档
  • 深入理解跳表:多层索引加速查找的经典实现
  • 从 “Hello AI” 到企业级应用:Spring AI 如何重塑 Java 生态的 AI 开发