当前位置: 首页 > 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.dtcms.com/a/318661.html

相关文章:

  • C语言:指针(1-2)
  • 亚马逊新品实现快速起量:如何设置有效的广告竞价策略
  • Java保姆级新手教程第三章(方法与数组)
  • 亚马逊广告进阶指南:广告转化的基本原理
  • 前端性能优化实战:电商首页从 10s 加载到 1s 的踩坑与复盘
  • 大数据存储域——HDFS存储系统
  • 在LLM小型化趋势下,AI Infra需要做出哪些相应调整?
  • 用 “私房钱” 类比闭包:为啥它能访问外部变量?
  • 日记研究:一种深入了解用户真实体验的UX研究方法
  • 【2025CVPR-目标检测方向】FIRE:通过频率引导重建误差对扩散生成的图像进行鲁棒检测
  • 2025AI论文工具测评?个人实测5款AI工具论文写作使用体验对比
  • 【pytorch(02)】Tensor(张量)概述、如何创建、常见属性,切换设备
  • 【0基础PS】PS工具详解--直接选择工具
  • TypeScript 数组类型精简知识点
  • 文本编码扫盲及设计思路总结
  • Mongodb入门介绍
  • [Python 基础课程]学生语文成绩录入和查询需求
  • [假面骑士] 555浅谈
  • AI大语言模型如何重塑软件开发与测试流程
  • Linux操作系统启动项相关研究与总结
  • 高速信号设计之 UPI2.0 篇
  • Spring Security 框架深度集成与开发指南
  • 如何设计一个开放授权平台?
  • 初识神经网络01——认识PyTorch
  • k8s的存储之statefulset控制器
  • 【MyBatis新手避坑】详解 `Could not find resource ...Mapper.xml` 错误
  • Class30数据增广
  • Leetcode刷题营:字符串相关--第35,36题
  • 深度探索:非静态内部类不能定义 static 成员属性和方法 及 静态内部类的必要性
  • 若依前后端分离版学习笔记(六)——JWT