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

【算法训练营Day21】回溯算法part3

文章目录

  • 分割回文串
  • 复原IP地址
  • 子集
  • 子集 II

分割回文串

题目链接:131. 分割回文串

解题逻辑:

本题的思考方式还是把问题要抽象成一个树形,前文中的组合问题我们大多都是进行递归取数的操作,在本题中变换为了递归切割。我们以“aab”串为例子来构造整个递归的树形结构。

在这里插入图片描述
了解了整个递归的大致流程之后,我们从递归三要素来分析这个问题:

  • 递归返回值、参数:返回值为void,参数有三个:第一个是要切割的字符串s,第二个是本次要切割的索引devideIndex,第三个是上次切割的索引lastDevideIndex。这样通过第二、三个参数我们就可以确定本次要切割的部分。
  • 递归出口:当本次要切割的索引devideIndex超过字符串的长度的时候,收集结果存入结果集
  • 递归逻辑:
    • 从当前位置循环往后切割
    • 判断本次切割的部分是否满足回文串,若不满足则跳过该次循环。如何判断回文子串?我们可以在字符串两头初始化双指针,以相同步幅往中间移动,如果直到两指针相遇两指针所指字符全都一样,那么就说明是回文子串
    • 若满足,将本次切割的部分加入到单个收集容器中
    • 递归进行下一次切割
    • 退出递归之后将收集容器的最后一个元素弹出来

代码如下:

class Solution {List<String> item = new ArrayList<>();List<List<String>> result = new ArrayList<>();public List<List<String>> partition(String s) {backtracking(s,1,0);return result;}public void backtracking(String s,int devideIndex,int lastDevideIndex){if(devideIndex > s.length()) {result.add(new ArrayList<String>(item));return;}for(int i = devideIndex;i <= s.length();i++) {StringBuilder word = new StringBuilder(s.substring(lastDevideIndex,i));if (!check(word)) continue;item.add(word.toString());backtracking(s,i + 1,i);item.remove(item.size() - 1);}}private boolean check(StringBuilder sb){for (int i = 0; i < sb.length()/ 2; i++){if (sb.charAt(i) != sb.charAt(sb.length() - 1 - i)){return false;}}return true;}
}

复原IP地址

题目链接:93. 复原 IP 地址

这一题与上一题分割回文串的思路差不多,区别在于本题要固定切四下来确定ip地址的四个部分并且字符串的每一位都要用到。

解题代码如下:

class Solution {List<String> ip = new ArrayList<>();List<String> result = new ArrayList<>();public List<String> restoreIpAddresses(String s) {backtracking(s,1,0);return result;}public void backtracking(String s,int insertIndex,int lastInsertIndex){if(ip.size() == 4) {if(lastInsertIndex != s.length()) return;String temp = String.join(".",ip);result.add(temp);return;}for(int i = insertIndex;i <= s.length();i++) {String part = s.substring(lastInsertIndex,i);if (!isValid(part)) continue;ip.add(part);backtracking(s,i + 1,i);ip.remove(ip.size() - 1);}}public static boolean isValid(String s) {// 检查是否有前导0(长度大于1且以0开头)if (s.length() > 1 && s.charAt(0) == '0') {return false;}// 转换为数字并检查范围try {int num = Integer.parseInt(s);return num >= 0 && num <= 255;} catch (NumberFormatException e) {// 如果转换失败,说明数字太大return false;}}
}

子集

题目链接:78. 子集

解题逻辑:

本题的解题逻辑与前文中的组合问题非常地相似,我们知道组合问题是在N个数里面按一定规则找出k个数的集合。在子集问题中没有k个数的限制,在代码中对应的变化就是收集结果的位置不一样。

代码如下:

class Solution {List<Integer> item = new ArrayList<>();List<List<Integer>> result = new ArrayList<>();public List<List<Integer>> subsets(int[] nums) {backtracking(nums,0);result.add(new ArrayList<Integer>());return result;}public void backtracking(int[] nums,int startIndex){if(item.size() >= nums.length) return;for(int i = startIndex;i < nums.length;i++) {item.add(nums[i]);result.add(new ArrayList<Integer>(item));backtracking(nums,i + 1);item.remove(item.size() - 1);}}
}

子集 II

题目链接:90. 子集 II

解题逻辑:

本题相当于把上道子集与前文中的组合总和II的去重逻辑相结合。直接照搬前面的思想即可。

解题代码:

class Solution {List<Integer> item = new ArrayList<>();List<List<Integer>> result = new ArrayList<>();public List<List<Integer>> subsetsWithDup(int[] nums) {Arrays.sort(nums);backtracking(nums,0);result.add(new ArrayList<Integer>());return result;}public void backtracking(int[] nums,int startIndex){if(item.size() >= nums.length) return;int old = Integer.MIN_VALUE;for(int i = startIndex;i < nums.length;i++) {if(old == nums[i]) continue;item.add(nums[i]);result.add(new ArrayList<Integer>(item));backtracking(nums,i + 1);item.remove(item.size() - 1);old = nums[i];}}
}
http://www.lryc.cn/news/611554.html

相关文章:

  • Redis的分布式序列号生成器原理
  • 【C++详解】STL-set和map的介绍和使用样例、pair类型介绍、序列式容器和关联式容器
  • 部署 Zabbix 企业级分布式监控笔记
  • 无人机开发分享——基于行为树的无人机集群机载自主决策算法框架搭建及开发
  • 分布式微服务--GateWay(1)
  • 3479. 水果成篮 III
  • Minio 高性能分布式对象存储
  • 分布式光伏气象站:安装与维护
  • 【论文分析】【Agent】SEW: Self-Evolving Agentic Workflows for Automated Code Generatio
  • 支持多网络协议的测试工具(postman被无视版)
  • 【概念学习】早期神经网络
  • ORACLE 19C建库时卡在46%、36%
  • Godot ------ 初级人物血条制作01
  • OpenAI开源大模型gpt-oss系列深度解析:从120B生产级到20B桌面级应用指南
  • Unity3D中的Controller:深入解析动画控制器的核心概念与应用
  • 【数据库】Oracle学习笔记整理之一:ORACLE的核心组成部分
  • 【YOLOv8改进 - C2f融合】C2f融合DBlock(Decoder Block):解码器块,去模糊和提升图像清晰度
  • 微信小程序最大层级跳转问题
  • [Oracle] SIGN()函数
  • RabbitMQ 全面指南:从基础概念到高级特性实现
  • Unix/Linux 系统编程中用于管理信号处理行为的核心概念或模型
  • 外观模式(Facade Pattern)及其应用场景
  • Leetcode-3488距离最小相等元素查询
  • 系统的缓存(buff/cache)是如何影响系统性能的?
  • 第五十篇:AI画家的“神经中枢”:ComfyUI的推理路径与缓存逻辑深度解析
  • 【Web安全】csrf、ssrf和xxe的区别
  • Python实现电商商品数据可视化分析系统开发实践
  • Qt 中实现多线程的两种方式及结合
  • Pytest项目_day05(requests加入headers)
  • 8.6 JavaWeb(请求响应 P67-P74)