算法解析-经典150(双指针、滑动窗口)

文章目录

  • 双指针
    • 1.验证回文串
        • 1.答案
        • 2.思路
    • 2.判断子序列
        • 1.动态规划解法
        • 2.双指针
    • 3.两数之和 II - 输入有序数组
        • 1.答案
        • 2.思路
    • 4.盛最多水的容器
        • 1.答案
        • 2.思路
    • 5.三数之和
        • 1.答案
        • 2.思路
  • 滑动窗口
    • 1.长度最小的子数组
        • 1.答案
        • 2.思路
    • 2.无重复字符的最长子串
        • 1.答案
        • 2.思路
    • 3.最小覆盖子串
        • 1.答案
        • 2.思路

双指针

1.验证回文串

1.答案
package com.sunxiansheng.classic150.g1;/*** Description: 125. 验证回文串** @Author sun* @Create 2024/12/19 15:03* @Version 1.0*/
public class t125 {public static boolean isPalindrome(String s) {// 直接双指针int left = 0;int right = s.length() - 1;while (left < right) {// 获取左右字符char leftChar = s.charAt(left);char rightChar = s.charAt(right);// 如果不是数字和字母,就直接下一位if (!Character.isDigit(leftChar) && !Character.isLetter(leftChar)) {left++;continue;}if (!Character.isDigit(rightChar) && !Character.isLetter(rightChar)) {right--;continue;}// 大写转换小写leftChar = Character.isUpperCase(leftChar) ? Character.toLowerCase(leftChar) : leftChar;rightChar = Character.isUpperCase(rightChar) ? Character.toLowerCase(rightChar) : rightChar;// 到这里左右都是数字字母字符了,可以直接比较if (leftChar != rightChar) {return false;}left++;right--;}return true;}public static void main(String[] args) {System.out.println("isPalindrome(\"A man, a plan, a canal: Panama\") = " + isPalindrome("A man, a plan, a canal: Panama"));}
}
2.思路

就是直接使用双指针,如果不是数字和字母,就直接下一位,大写转换小写,然后比较即可

2.判断子序列

1.动态规划解法
package com.sunxiansheng.classic150.g1;/*** Description: 392. 判断子序列** @Author sun* @Create 2024/12/21 09:36* @Version 1.0*/
public class t392 {public boolean isSubsequence(String s, String t) {// dp[i][j]:以i-1,j-1为结尾的最长公共子序列的长度// 状态转移公式:相同时 dp[i][j] = dp[i - 1][j - 1] + 1 不同时 dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])// 初始化int m = s.length();int n = t.length();int[][] dp = new int[m + 1][n + 1];int max = 0;// 填充dp数组for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (s.charAt(i - 1) == t.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}max = Math.max(max, dp[i][j]);}}return max ==  s.length();}
}
2.双指针
package com.sunxiansheng.classic150.g1;/*** Description: 392. 判断子序列** @Author sun* @Create 2024/12/21 09:36* @Version 1.0*/
public class t392 {public static boolean isSubsequence(String s, String t) {// 双指针int left = 0;for (int right = 0; right < t.length(); right++) {// 如果左数组已经遍历完了就提前退出if (left >= s.length()) {break;}// 当右指针遇到了左指针指向的元素,左指针++if (t.charAt(right) == s.charAt(left)) {left++;}}return left >= s.length();}
}

3.两数之和 II - 输入有序数组

1.答案
package com.sunxiansheng.classic150.g1;/*** Description: 167. 两数之和 II - 输入有序数组** @Author sun* @Create 2024/12/21 10:08* @Version 1.0*/
public class t167 {public int[] twoSum(int[] numbers, int target) {// 两个指针从两边往中间移动int left = 0;int right = numbers.length - 1;while (left < right) {// 求和int sum = numbers[left] + numbers[right];// 如果大于target,就右指针移动,小于target就左指针移动if (sum > target) {right--;} else if (sum < target) {left++;} else {return new int[]{left + 1, right + 1};}}return null;}
}
2.思路

这里用的是贪心双指针,就是两个指针从两边往中间移动,和如果大于target,就右指针移动,小于target就左指针移动

4.盛最多水的容器

1.答案
package com.sunxiansheng.classic150.g1;/*** Description: 11. 盛最多水的容器** @Author sun* @Create 2024/12/21 10:42* @Version 1.0*/
public class t11 {public static int maxArea(int[] height) {int max = 0;int left = 0, right = height.length - 1;while (left < right) {// 求水量int water = Math.min(height[left], height[right]) * (right - left);// 更新最大值max = Math.max(max, water);// 哪边低移动哪边的指针if (height[left] < height[right]) {left++;} else {right--;}}return max;}
}
2.思路

使用贪心双指针解决

5.三数之和

1.答案
package com.sunxiansheng.classic150.g1;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** Description: 15. 三数之和** @Author sun* @Create 2024/12/21 10:50* @Version 1.0*/
public class t15 {public static List<List<Integer>> threeSum(int[] nums) {// 使用遍历+贪心双指针来解决List<List<Integer>> res = new ArrayList<>();// 如果数组长度小于3,直接返回空结果if (nums == null || nums.length < 3) {return res;}// 首先排序Arrays.sort(nums);// 遍历for (int i = 0; i < nums.length - 2; i++) {// 关键点:当前的元素跟前一个元素是相同的情况下不必考虑if (i > 0 && nums[i] == nums[i - 1]) {continue;}// 贪心双指针int left = i + 1;int right = nums.length - 1;while (left < right) {// 求结果int sum = nums[left] + nums[right] + nums[i];// 根据结果来贪心的调整状态if (sum > 0) {right--;} else if (sum < 0) {left++;} else {res.add(Arrays.asList(nums[i], nums[left], nums[right]));// 关键点:当左右指针指向的下一个元素跟当前元素是相同的也不用考虑while (left < right && nums[left] == nums[left + 1]) {left++;}while (left < right && nums[right] == nums[right - 1]) {right--;}left++;right--;}}}return res;}
}
2.思路

使用遍历+贪心双指针来解决,注意两个关键点一个是在遍历时,遇到重复元素就跳过,另一个是在左右指针移动时,遇到重复元素也跳过

滑动窗口

1.长度最小的子数组

1.答案
package com.sunxiansheng.classic150.g1;/*** Description: 209. 长度最小的子数组** @Author sun* @Create 2024/12/21 11:20* @Version 1.0*/
public class t209 {public static int minSubArrayLen(int target, int[] nums) {// 滑动窗口定义:窗口内的元素要小于targetint left = 0;int res = Integer.MAX_VALUE;int sum = 0;for (int right = 0; right < nums.length; right++) {// 加入窗口sum += nums[right];// 只要窗口内的元素是大于target的,就进行处理while (sum >= target) {// 计算结果res = Math.min(res, right - left + 1);// 滑动窗口sum -= nums[left++];}}return res == Integer.MAX_VALUE ? 0 : res;}
}
2.思路

先进行滑动窗口的定义窗口内的元素要小于target,那么只要窗口内的元素是大于target的,就进行处理,就可以计算结果了

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

1.答案
package com.sunxiansheng.classic150.g1;import java.util.HashSet;
import java.util.Set;/*** Description: 3. 无重复字符的最长子串** @Author sun* @Create 2024/12/21 11:28* @Version 1.0*/
public class t3 {public static int lengthOfLongestSubstring(String s) {// 滑动窗口定义:窗口内的元素不能重复int left = 0;int res = 0;Set<Character> set = new HashSet<>();for (int right = 0; right < s.length(); right++) {// 获取set的长度int before = set.size();// 加入窗口set.add(s.charAt(right));res = Math.max(res, set.size());// 当窗口内的元素重复时if (set.size() == before) {while (s.charAt(left) != s.charAt(right)) {// 滑动窗口set.remove(s.charAt(left));left++;}// 到这里就说明当前left指向了那个重复元素,继续滑动窗口,不过不需要移动setleft++;}}return res;}
}
2.思路

这里面比较复杂一点,十分考察对滑动窗口算法的理解,加入窗口前先要获取一下加入set之前的长度,如果加入窗口后长度不变,那么就一定是元素重复了,需要滑动窗口直到不重复。计算结果则是在加入窗口的时候

3.最小覆盖子串

1.答案
package com.sunxiansheng.classic150.g1;import java.util.HashMap;
import java.util.Map;/*** Description: 76. 最小覆盖子串** @Author sun* @Create 2024/12/21 14:19* @Version 1.0*/
public class t76 {public static String minWindow(String s, String t) {// 滑动窗口定义:窗口内元素不能全部包含t的所有元素// 使用map来记录t的词频Map<Character, Integer> tMap = new HashMap<>();for (int i = 0; i < t.length(); i++) {tMap.put(t.charAt(i), tMap.getOrDefault(t.charAt(i), 0) + 1);}// 所有的字符数(当满足条件的字符数为n时,表明该子串就是覆盖子串了)int n = t.length();// 满足条件的字符数int satisfy = 0;// s的词频Map<Character, Integer> sMap = new HashMap<>();// 最小覆盖子串的长度int minSonLength = Integer.MAX_VALUE;// 最小覆盖子串String minSon = "";int left = 0;for (int right = 0; right < s.length(); right++) {// 获取到目标字符char c = s.charAt(right);// 只考虑是t的元素的情况if (tMap.containsKey(c)) {// 加入窗口sMap.put(c, sMap.getOrDefault(c, 0) + 1);// 如果目标字符的出现次数是小于t中的频率,就可以增加满足条件的字符数if (sMap.get(c) <= tMap.get(c)) {satisfy++;}}// 只要目前是覆盖子串,就需要滑动窗口while (satisfy == n) {// 更新最小覆盖子串if ((right - left + 1) < minSonLength) {minSon = s.substring(left, right + 1);minSonLength = right - left + 1;}// 滑动窗口// 当是t的元素时if (tMap.containsKey(s.charAt(left))) {// 更新词频和满足的字符数sMap.put(s.charAt(left), sMap.get(s.charAt(left)) - 1);// 只有当窗口中的元素减少后,确实比t中的词频少了,才会减少满足的字符数if (sMap.get(s.charAt(left)) < tMap.get(s.charAt(left))) {satisfy--;}}// 不是t的元素就直接滑动即可left++;}}return minSon;}public static void main(String[] args) {minWindow("ADOBECODEBANC", "ABC");}
}
2.思路

核心就是使用Map来记录两个字符串的词频,然后当满足条件的字符数量为t的个数时就是覆盖子串

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Vim Masterclass 笔记05】第 4 章:Vim 的帮助系统与同步练习

文章目录 Section 4&#xff1a;The Vim Help System&#xff08;Vim 帮助系统&#xff09;S04L14 Getting Help1 打开帮助系统2 退出帮助系统3 查看具体命令的帮助文档4 查看帮助文档中的主题5 帮助文档间的上翻、下翻6 关于 linewise7 查看光标所在术语名词的帮助文档8 关于退…

java Redisson 实现限流每秒/分钟/小时限制N个

1.引入maven包: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.redisson</groupId><artifactId>red…

C# 标准数字格式字符串

总目录 前言 当前文章为 C# 中的格式设置(格式化字符串) 大全 中的一个小章节。 一、概述 1. 基本信息 标准数字格式字符串用于格式化通用数值类型。标准数字格式字符串采用 [format specifier][precision specifier] 的形式 format specifier 格式说明符&#xff0c;负责指…

网络分析工具-tcpdump

文章目录 前言一、tcpdump基础官网链接命令选项详解常规过滤规则tcpdump输出 一、tcpdump实践HTTP协议ICMP状态抓包 前言 当遇到网络疑难问题的时候&#xff0c;抓包是最基本的技能&#xff0c;通过抓包才能看到网络底层的问题 一、tcpdump基础 tcpdump是一个常用的网络分析工…

【微软,模型规模】模型参数规模泄露:理解大型语言模型的参数量级

模型参数规模泄露&#xff1a;理解大型语言模型的参数量级 关键词&#xff1a; #大型语言模型 Large Language Model #参数规模 Parameter Scale #GPT-4o #GPT-4o-mini #Claude 3.5 Sonnet 具体实例与推演 近日&#xff0c;微软在一篇医学相关论文中意外泄露了OpenAI及Claud…

springboot集成qq邮箱服务

springboot集成qq邮箱服务 1.获取QQ邮箱授权码 1.1 登录QQ邮箱 1.2 开启SMTP服务 找到下图中的SMTP服务区域&#xff0c;如果当前账号未开启的话自己手动开启。 1.3 获取授权码 进入上图中的【管理服务】后&#xff1a;在【安全设置中生成授权码】,也可以直接点击【继续生成…

Windows系统提示ffmpeg.dll丢失怎么解决?

一、了解ffmpeg.dll文件 ffmpeg.dll是FFmpeg项目的一个动态链接库文件&#xff0c;FFmpeg是一个开源的多媒体处理框架&#xff0c;能够解码、编码、转码、混流、过滤和播放几乎所有已知格式的音频和视频文件。当Windows系统提示ffmpeg.dll丢失时&#xff0c;通常意味着某个需要…

直观解读 JuiceFS 的数据和元数据设计(一)

大家读完觉得有意义和帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 1 JuiceFS 高层架构与组件2 搭建极简 JuiceFS 集群 2.1 搭建元数据集群2.2 搭建对象存储&#xff08;MinIO&#xff09; 2.2.1 启动 MinIO server2.2.2 创建 bucket2.3 下载 juicefs 客户端2.4 创…

分布式微服务项目___某污水处理项目

一.分布式微服务项目___污水处理项目 项目地址:https://gitee.com/yanyigege/collaborative-water-springboot.git ​ 1.项目背景 总公司在全国各地有处理污水的项目部,各项目部处理自己的污水,总部需要监控各地分项目部每天处理污水的原料用量,掌握各分部的污水处理情况 ​…

鸿蒙HarmonyOS开发:拨打电话、短信服务、网络搜索、蜂窝数据、SIM卡管理、observer订阅管理

文章目录 一、call模块&#xff08;拨打电话&#xff09;1、使用makeCall拨打电话2、获取当前通话状态3、判断是否存在通话4、检查当前设备是否具备语音通话能力 二、sms模块&#xff08;短信服务&#xff09;1、创建短信2、发送短信 三、radio模块&#xff08;网络搜索&#x…

TVS二极管选型【EMC】

TVS器件并联在电路中&#xff0c;当电路正常工作时&#xff0c;他处于截止状态&#xff08;高阻态&#xff09;&#xff0c;不影响线路正常工作&#xff0c;当线路处于异常过压并达到其击穿电压时&#xff0c;他迅速由高阻态变为低阻态&#xff0c;给瞬间电流提供一个低阻抗导通…

sqlalchemy-access库操作MS Access

因目前项目中数据处理的量稍大&#xff0c;为了方便和业务进行交互&#xff0c;对数据的加工和处理放到微软桌面数据库MS Access中。然后有些地方通过 Python 来操作 MS Access 数据库&#xff0c;用到 sqlalchemy-access库。本文对操作的要点做简单的描述。 之前写过一篇 Pyt…

UnityRenderStreaming使用记录(三)

测试UnityRenderStreaming在Ubuntu24.04.1LTS上的表现 先放上运行图操作系统 Ubuntu24.04.1LTSUnity测试工程环境相关修改遇到的问题 先放上运行图 操作系统 Ubuntu24.04.1LTS 系统下载地址 https://cn.ubuntu.com/download/desktop安装UnityHub https://blog.csdn.net/AWNUXC…

==和===的区别,被坑的一天

在 JavaScript 中&#xff0c; 和 都用于比较两个值&#xff0c;但它们有一个重要的区别&#xff1a; 1. (宽松相等运算符) 进行比较时&#xff0c;会 自动类型转换&#xff08;也叫做强制类型转换&#xff09;&#xff0c;即如果比较的两个值的类型不同&#xff0c;JavaScr…

Git的使用流程(详细教程)

目录 01.Git是什么&#xff1f; 1.1 Git简介 1.2 SVN与Git的最主要的区别 1.3 GIt主要特点 02.Git是干什么的&#xff1f; 2.1.Git概念汇总 2.2 工作区/暂存区/仓库 2.3 Git使用流程 03.Git的安装配置 3.1 Git的配置文件 3.2 配置-初始化用户 3.3 Git可视化…

使用Docker部署最新版JupyterHub

拉取镜像 docker pull jupyterhub/jupyterhub:latest启动镜像 docker run -d -p 8000:8000 --name jupyterhub jupyterhub/jupyterhub:latest jupyterhub进入容器 docker exec -it jupyterhub bash生成jupyterhub的配置文件 jupyterhub --generate-config# 有需要可以安装中…

liunx下载gitlab

1.地址&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ 安装 postfix 并启动 yum install postfix systemctl start postfix systemctl enable postfix ssh服务启动 systemctl enable sshd systemctl start sshd开放 ssh 以及 http 服务&#xff0c…

【AI大模型】深入GPT-2模型细节:揭秘其卓越性能的秘密

目录 &#x1f354; GPT2的架构 &#x1f354; GPT2模型的细节 2.1 模型过程 2.2 GPT2工作细节探究 &#x1f354; 小结 学习目标 掌握GPT2的架构掌握GPT2的训练任务和模型细节 &#x1f354; GPT2的架构 从模型架构上看, GPT2并没有特别新颖的架构, 它和只带有解码器模块…

oceanbase集群访问异常问题处理

1.报错现象 2.问题排查 检查obproxy状态发现为不可用状态 重启obproxy 依次重启Obproxy集群 观察任务状态 重启完成 Obproxy状态正常 3.验证登录 登录成功

Echarts+vue电商平台数据可视化——webSocket改造项目

websocket的基本使用&#xff0c;用于测试前端能否正常获取到后台数据 后台代码编写&#xff1a; const path require("path"); const fileUtils require("../utils/file_utils"); const WebSocket require("ws"); // 创建WebSocket服务端的…