算法学习day26

news2025/1/15 12:48:06

滑动窗口系列题

一、替换后的最长重复子串

给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。

在执行上述操作后,返回 包含相同字母的最长子字符串的长度。

输入:s = "AABABBA", k = 1
输出:4 AABA BABB
思路:滑动窗口 滑动窗口的大小是根据条件得到的,不是题目中规定好的。

滑动窗口就是能够装更多的重复字母的窗口。:满足条件的时候滑动窗口就扩容,不满足条件的时候滑动窗口左边界移动

那么?这里的条件是什么:滑动窗口的长度<+重复的字母+可以替换的次数。也就是说如果窗口中需要替换的次数<=可以替换的次数,那么该滑动窗口就仍然有效,否则就要移动。

left:滑动窗口的左边界  right:滑动窗口的右边界  maxLen:某个滑动窗口中重复最多的字母。

1.首先,遍历到某一个字母的时候,把它存到数组中 arr[s.charAt(i)-'A']++; 然后更新maxLen

2.判断此时滑动窗口是扩容还是左边界改变。

   2.1 if(right-left+1>maxLen+k) 此时就要左边界改变 arr[s.charAt(left)-'A']--;left++;

   2.2 反之,更新一下滑动窗口的最大长度(也就是要求的结果 最长重复子串):res=Math.max(res,right-left+1);

总结:

其实就是在不断寻找最长滑动窗口长度的过程。滑动窗口的大小只能增大不能减小。

代码:
class Solution {
    public int characterReplacement(String s, int k) {
        int left=0,right=0;
        int res=0;
        int maxLen=-1;
        char[] ch=new char[26];
        while(right<s.length()){
            char c=s.charAt(right);
            ch[c-'A']++;
            maxLen=Math.max(maxLen,ch[c-'A']);
            if(right-left+1>maxLen+k){
                ch[s.charAt(left)-'A']--;
                left++;
            }
            res=Math.max(res,right-left+1);
            right++;
        }
        return res;
    }
}

二、最大连续1的个数(滑动窗口)


给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数。

输入: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。
模拟:

1. 0,0,1,1,0,0 此时maxLen+k<right-left+1 此时滑动窗口的左边界+1; left为0

2. 0,1,1,0,0,1 此时是滑动窗口长度增大的过程 直到增长到1,1,0,0,1,1,1,0,1,1 此时maxLen+k=10

left为2

3. 到1,0,0,1,1,1,0,1,1之后,就再也没有机会能使滑动窗口扩容了,此后滑动窗口的长度一直保持left-right+1;

思路:

当遇到1的时候,cnt++;maxLen=Math.max(cnt,maxLen);直到maxLen+k<right-left+1的时候,说明滑动窗口无法继续扩容了,此时将左边界右移一位,此时的right-left+1就是滑动窗口的大小(也就是maxLen+k) 通过cnt变大,使得maxLen取最大,从而使得滑动窗口maxLen+k变最大

代码:

class Solution {
    public int longestOnes(int[] nums, int k) {
        int cnt=0;
        int left=0;
        int right=0;
        int maxLen=0;
        int res=-1;
        while(right<nums.length){
            if(nums[right]==1)cnt++;
            maxLen=Math.max(maxLen,cnt);
            while(right-left+1>maxLen+k){
                if(nums[left]==1)cnt--;
                left++;
            }
            res=Math.max(res,right-left+1);
            right++;
        }
        return res;
    }
}

三、尽可能使字符串相等(滑动窗口)

题意:

给你两个字符串s,t;s[i]和t[i]的ASCII值的绝对值为转换的开销。在给定一个maxCost的前提下,求可以转换的最大长度。

输入:s = "abcd", t = "bcdf", maxCost = 3
输出:3
解释:s 中的 "abc" 可以变为 "bcd"。开销为 3,所以最大长度为 3。
思路:滑动窗口

利用滑动窗口,主要是判断什么时候扩容,什么时候左边界右移;

1.扩容,当totalCost<=maxCost的时候,right++。移动之后更新totalCost

2.右移:  当totalCost>maxCost的时候,左边界就要右移,left++;移动之后更新totalCost;

3.在移动的过程中记录最大的长度即,res=Math.max(res,right-left+1);

代码:
class Solution {
    public int equalSubstring(String s, String t, int maxCost) {
        int totalCost=0;
        int left=0;
        int right=0;
        int res=0;
        while(right<t.length()){
            totalCost+=Math.abs(s.charAt(right)-t.charAt(right));
            if(totalCost>maxCost){
                totalCost-=Math.abs(s.charAt(left)-t.charAt(left));
                left++;
            }
            res=Math.max(res,right-left+1);
            right++;
        }
        return res;
    }
}

四、最小覆盖子串(滑动窗口) 

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

题意:

在s串中寻找涵盖t串的最小子串,并且返回最小子串;如果不存在就返回"";

思路:

要在s串中寻找涵盖t串的最小子串。

1.先将t串的字符和数量都统计起来(使用数组和map都可以),这里使用数组进行统计字符的种类,count统计字符的数量

2.统计完毕之后就开始在s串进行遍历了。如果遍历到的字符是字符中出现的字符,那么count--;

如果count==0的话,就说明找到了一个子串涵盖t串,此时右边界为right

3.找到右边界之后,对左边界进行压缩,if(--cnt[s.charAt(left)]>0),就说明letf所指向的该元素是在t串中出现的,因此左边界不能再移动了。此时更新子串的长度。right-left;

代码:先固定右边界 再固定左边界
class Solution {
    public String minWindow(String s, String t) {
        char[] ch1 = s.toCharArray();
        char[] ch2 = t.toCharArray();
        int[] cnt = new int[128];
        int count = 0;
        // 将t串中的字符都收集起来
        for (char ch : ch2) {
            cnt[ch - 'A']++;
            count++;
        }
        // 遍历s串
        int left = 0, start = -1, end = s.length();
        for (int right = 0; right < s.length(); right++) {
            // 如果遍历到的该字符 在t串中出现过的 就count--
            if (--cnt[ch1[right] - 'A'] >= 0)
                count--;
            // 在s中找到子串
            while (count == 0) {
                // 如果当前left所指向的字符是t串中出现的字符 那么就不能向右更新了
                if (++cnt[ch1[left] - 'A'] > 0) {
                    if (right - left < end - start) {
                        end = right;
                        start = left;
                    }
                    count++;
                }
                left++;// 当前left还能继续移动
            }
        }
        return start == -1 ? "" : s.substring(start, end + 1);
    }
}

快慢指针应用

五、环形链表II

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

思路:

1.首先判断环形链表是否有环,可以根据快慢指针是否相等判断。慢指针每次移动一个距离,快指针每次移动两个距离,如果有环的话,那么快指针可以由领先(在慢指针的前面)再到落后(在慢指针的后面)再到相等。因为快指针每次追一个距离,差距每次-1,差距为0的时候,就相遇了

2.有环则一定有入口,根据公式2(x+y)=n*(y+z)+x+y,得到x=(n-1)(y+z)+z;可以得到

起点到入口的距离 == 相遇的点到起点的距离(顺时针)

代码:
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head==null||head.next==null)return null;
        ListNode slow=head;
        ListNode fast=head;
        while(fast!=null&&fast.next!=null&&fast.next.next!=null){
            slow=slow.next;
            fast=fast.next.next;
            //快慢指针相遇 说明有环
            if(slow==fast){
                ListNode index1=slow;
                ListNode index2=head;
                while(index1!=index2){
                    index1=index1.next;
                    index2=index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}

六、重排链表(寻找中间值+翻转链表)

给定一个单链表 L 的头节点 head ,单链表 L 表示为:L0 → L1 → … → Ln - 1 → Ln

请将其重新排列后变为:L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

题意:按照 1,n,2,n-1,3,n-2的规律排列
思路:找到中间值,变成两段序列(0->中间值前一个)、(中间值->最后)。将中间值以后的序列反转。反转之后两端序列依次出一个然后形成一段链表

1->2->3->4->5 

1.找中间值 3。分成两段:1->2\ 3->4->5 

2.中间值作为新的头结点反转 5->4->3

3.1->2\ 5->4->3 左边拿一个 右边拿一个 1->5->2->4->3

代码:
class Solution {
    public void reorderList(ListNode head) {
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
        }
        //slow就是中间值 将中间值为新的起点 进行翻转
        ListNode pre=null;
        while(slow!=null){
            ListNode temp=slow.next;
            slow.next=pre;
            pre=slow;
            slow=temp;
        }
        //反转完了 此时pre就是新的头结点
        while(pre.next!=null){
            ListNode temp1=head.next;
            ListNode temp2=pre.next;
            head.next=pre;
            pre.next=temp1;
            head=temp1;
            pre=temp2;
        }
    }
}

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

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

相关文章

MySQL--MySQL函数

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 MySQL函数 一、MySQL函数简介 函数表示对输入参数值返回一个具有特定关系的值&#xff0c;MSOL提供了大量丰富的函数&#xff0c;在进行数据库管理以…

CTFHub——XSS全系列

1、反射型&#xff1a; 发现为表单式&#xff0c;猜测哪个可能存在注入漏洞&#xff0c;分别做测试注入发现name框存在xss漏洞 输入发现有回显但不是对方cookie&#xff0c;参考wp发现要用xss线上平台 将xss平台测试语句注入&#xff0c;将得到的url编码地址填入url框&#xf…

Mongodb集合操作

文章目录 1、进入容器2、如果数据库不存在&#xff0c;则创建数据库&#xff0c;否则切换到指定数据库3、在 MongoDB 中&#xff0c;创建集合不是必须操作。当你插入一些文档时&#xff0c;MongoDB 会自动创建集合。4、查看数据库列表5、查看集合6、显示创建集合7、删除集合 1、…

Raspberry Pi Docker 运行 IRIS

在 Raspberry Pi 上成功安装 Docker 后可以安装 IRIS 数据库。 安装的命令为&#xff1a; docker run --name my-iris -d --publish 1972:1972 --publish 52773:52773 intersystems/irishealth-community:latest-em-linux-arm64v8 注意&#xff0c;我们这里暴露了 2 个端口&a…

Spring框架 配置Gateway网关/spring cloud gateway 基础入门案例教程

文章目录 目录 文章目录 安装流程 小结 概要安装流程技术细节小结 概要 网关作为微服务集群唯一的对外入口,可以实现很多功能. 例如: 统一的解决跨域(一个ajax请求 origin域名和请求目标url中域名不同,ip不同,域名不同,端口不同,都会引发的问题)问题. 统一的身份认证.认证解…

OpenStack Yoga版安装笔记(十)placement练习

1、练习场景说明 在OpenStack Yoga版安装笔记&#xff08;九&#xff09;中&#xff0c;placement已经在controller node虚拟机上安装完成&#xff0c;并且已经成功拍摄了快照。 此时&#xff0c;controller node虚机已经安装了keystone、keystone DB、glance、glance DB、Open…

反序列化漏洞vulhub靶场serial

环境搭建 下载 https://download.vulnhub.com/serial/serial.zip 解压出来就是这种 你会得到一个这样的文件&#xff0c;这里使用VMware新建一个虚拟机&#xff0c;这里记录比较重要的几部分。 这里就是使用我们刚才下过来的。 漏洞过程详解 1.信息收集 打开靶机&#xff0…

干货满满,从零到一:编程小白如何在大学成为编程大神?

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

Git(4) 解决Git相关问题的实用技巧

本文将介绍一些Git实用的技巧&#xff0c;实际操作中解决常见的Git问题。 问题1&#xff1a;将本地项目推送到远程仓库 如何将本地项目推送到远程仓库&#xff0c;包括处理常见错误的方法&#xff0c;并最终将代码推送到 main 分支。 步骤 1. 初始化本地仓库 确保已经在本地…

类和对象的深入了解6

1.初始化列表 初始化列表&#xff1a;以一个冒号开始&#xff0c;接着是一个以逗号分隔的数据成员列表&#xff0c;每个"成员变量"后面跟一个放在括 号中的初始值或表达式。 class Date { public:Date(int year, int month, int day): _year(year), _month(month),…

Cellpress|单细胞文章|单细胞转录和大队列食管癌免疫治疗

新辅助免疫检查点阻断 (ICB) 在可手术食管鳞状细胞癌 (ESCC) 中显示出希望&#xff0c;但缺乏可用的疗效生物标志物。该文章对接受新辅助 ICB 的 ESCC 患者的肿瘤进行单细胞 RNA 测序&#xff0c;发现一组表达SPRY1 (CD8 Tex-SPRY1) 的耗竭 CD8 T 细胞亚群&#xff0c;其显示…

72.结构体变量直接赋值

目录 一.结构体变量直接赋值 二.视频教程 一.结构体变量直接赋值 通过上节课的学习得出了一个结论&#xff1a;俩个相同类型的结构体变量直接可以只用赋值号进行赋值。 像这样&#xff1a; struct test {int a;int b; };int main(void) {struct test x {1,2};struct test …

反序列化靶机实战serial(保姆级教程)

一.信息收集 靶机地址下载&#xff1a;https://download.vulnhub.com/serial/serial.zip 打开靶机&#xff0c;在kali虚拟机中进行主机存活探测 可以知道靶机ip地址为192.168.133.171 然后扫描端口 可以发现有一个22端口跟80端口 然后接下来用kali扫描它的目录 可以发现有一…

10年仓库管理经验:“管、存、发、盘”一文搞定!

前段时间去一家仓储设备公司交流学习&#xff0c;和一位有着10年经验的老仓管聊了个痛快&#xff0c;从他那儿学到了不少仓库管理的实践方法。 回来自己整理了一套仓库管理高效的实用方法&#xff0c;现在就来跟大家伙儿聊聊仓库管理中那些常见问题&#xff0c;以及我是怎么琢…

vite构建vue3项目hmr不生效问题踩坑记录

vite构建vue3项目hmr不生效问题踩坑记录 hmr的好处 以下是以表格形式呈现的前端开发中HMR&#xff08;热模块替换&#xff09;带来的好处&#xff1a; 好处描述提升开发效率允许开发者在不刷新整个页面的情况下实时更新修改的代码&#xff0c;减少等待时间保持应用状态在模块…

技术分享| 前端性能优化——虚拟滚动(Virtual Scroll)

前端遇到大量数据&#xff08;尤其是大数据表&#xff09;的DOM 渲染时&#xff0c;通常会卡顿&#xff0c;需要考虑优化性能问题&#xff0c;这里针对DOM 渲染引出“虚拟滚动”方案&#xff0c; 详细请在以下各文章中详细了解&#xff1a; vue插件 vue-virtual-scroll-list解决…

C语言| 文件操作详解(二)

目录 四、有关文件的随机读写函数 4.1 fseek 4.2 ftell 4.3 rewind 五、判定文件读取结束的标准与读写文件中途发生错误的解决办法 5.1 判定文件读取结束的标准 5.2 函数ferror与feof 5.2.1 函数ferror 5.2.2 函数feof 在上一章中&#xff0c;我们主要介绍了文件类型…

鸿蒙系统开发【事件订阅】网络

事件订阅 介绍 本示例通过ohos.telephony.observer等接口订阅网络状态、信号状态、蜂窝数据、sim状态等事件&#xff0c;并获取状态变化返回的结果。 效果预览 使用说明 1.打开应用&#xff0c;开启所有订阅事件开关。 2.开关一次移动网络&#xff0c;触发网络状态变化。 …

Linux-4:Shell编程——基础语法(50%-100%)

目录 前言 一、数组 1.数组定义 2.关联数组 3.数组长度 二、运算符 1.算术运算符 2.关系运算符 3.布尔运算符 4.逻辑运算符 5.字符串运算符 6.文件测试运算符 三、read命令 1.接收用户输入 2.开启转义 3. -p 输入提示 4. -s 静默模式 -t 设置超时时间 5.读取…