leetcode热题HOT leetcode131. 分割回文串

2024-03-10 18:44

本文主要是介绍leetcode热题HOT leetcode131. 分割回文串,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、问题描述:

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
本题属于分割问题,for循环的暴力解法太耗时了 ,不太现实。考虑另一种暴力解法-回溯。这里可以参考Carl的回溯方法模板:

二、解题思路:

  1. 通过递归和回溯的方式,不断尝试各种分割方式,并判断每个子串是否为回文字符串,最终得到所有满足条件的分割结果。
  2. 具体步骤:
    ①定义一个全局变量 result 用于存储最终的结果,path 用于存储当前路径上的子串。
    ②partition 方法是整个算法的入口,它调用 partitions 方法进行递归分割。
    ③partitions 方法的作用是从位置 l 开始向后遍历字符串 s,对于每一个可能的子串,如果是回文字符串,则将其加入到 path 中,并递归处理剩余部分,最后将该子串移出 path。这样可以找出所有满足条件的分割情况。
    ④huiwen 方法用于判断字符串 s 中从位置 l 到位置 r 的子串是否为回文字符串,通过双指针法来进行判断。
    ⑤在递归过程中,不断尝试各种分割方式,并且在满足条件时将当前的路径加入到结果集中。最终返回结果集 result。
  3. 注意几个关键点:
    ①找到递归的终止条件:从起始点开始分割字符串,如果分割点startindex>= s.length(),说明分割完毕,找到一组解。
    ②在for (int i = l; i < s.length(); i++)循环中,我们定义了起始位置l,那么 [l, i] 就是要截取的子串。
    ③处理节点就是要判断这个子串是不是回文串,如果是回文,就加入path中,path用来记录切割过的回文子串,然后继续分割剩余的子串,起始位置变为i+1。如果不是回文串则continue 跳过,没必要继续分割了。

三、代码示例:

class Solution {List<List<String>> result = new ArrayList<>(); // 存储最终的结果LinkedList<String> path = new LinkedList<>(); // 存储当前路径上的子串public List<List<String>> partition(String s) {partitions(s, 0); // 调用递归方法进行字符串分割return result; // 返回最终结果}// 递归方法,对字符串 s 进行分割public void partitions(String s, int l) {if (l >= s.length()) { // 如果已经遍历完整个字符串 sresult.add(new ArrayList<>(path)); // 将当前路径加入到结果集中return;}for (int i = l; i < s.length(); i++) {if (huiwen(s, l, i)) { // 如果从位置 l 到位置 i 的子串是回文字符串path.add(s.substring(l, i + 1)); // 将该子串加入到当前路径中} else {continue; // 否则继续向后遍历}partitions(s, i + 1); // 递归处理剩余部分path.removeLast(); // 回溯,将最后加入的子串移出当前路径}}// 判断字符串 s 中从位置 l 到位置 r 的子串是否为回文字符串public boolean huiwen(String s, int l, int r) {while (l < r) {if (s.charAt(l) != s.charAt(r)) {return false; // 不是回文字符串}l++;r--;}return true; // 是回文字符串}
}
  • 时间复杂度分析:对于长度为 n 的字符串 s,最坏情况下有 2^n 种分割方式,因为每个字符都有可能是分割点或者不是分割点。
    在递归过程中,每一种分割情况都要判断其中的子串是否为回文字符串,这个判断操作的时间复杂度为 O(n)。
    因此,总体时间复杂度为 O(n * 2^n),即指数级别的复杂度。

四、补充与总结:

  1. 递归模板
void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集合中的元素) {处理单个节点;backtracking(路径,选择列表); // 递归回溯,撤销处理结果}
}
  1. 判断回文子串:字符串反转后和原字符串相同即为回文串,可用双指针法判断。
    private boolean huiwen(String s, int startIndex, int end) {for (int i = startIndex, j = end; i < j; i++, j--) {if (s.charAt(i) != s.charAt(j)) return false;}return true;}
  1. 字符串截取:通过subString()方法来进行字符串截取,返回字符串中的子字符串。

①传递一个参数:

public String substring(int beginIndex);
//子字符串从指定索引处的字符开始,到此字符串末尾。

②传递两个参数:

public String substring(int beginIndex, int endIndex);
//从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符。因此,该子字符串的长度为 endIndex-beginIndex。
//参数说明:beginIndex – 起始索引(包括)、endIndex – 结束索引(不包括)。

这篇关于leetcode热题HOT leetcode131. 分割回文串的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/795164

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

csu1328(近似回文串)

题意:求近似回文串的最大长度,串长度为1000。 解题思路:以某点为中心,向左右两边扩展,注意奇偶分开讨论,暴力解即可。时间复杂度O(n^2); 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>#include<string>#inclu

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

【JavaScript】LeetCode:16-20

文章目录 16 无重复字符的最长字串17 找到字符串中所有字母异位词18 和为K的子数组19 滑动窗口最大值20 最小覆盖字串 16 无重复字符的最长字串 滑动窗口 + 哈希表这里用哈希集合Set()实现。左指针i,右指针j,从头遍历数组,若j指针指向的元素不在set中,则加入该元素,否则更新结果res,删除集合中i指针指向的元素,进入下一轮循环。 /*** @param

SAM2POINT:以zero-shot且快速的方式将任何 3D 视频分割为视频

摘要 我们介绍 SAM2POINT,这是一种采用 Segment Anything Model 2 (SAM 2) 进行零样本和快速 3D 分割的初步探索。 SAM2POINT 将任何 3D 数据解释为一系列多向视频,并利用 SAM 2 进行 3D 空间分割,无需进一步训练或 2D-3D 投影。 我们的框架支持各种提示类型,包括 3D 点、框和掩模,并且可以泛化到不同的场景,例如 3D 对象、室