Leetcode 分割回文串

算法思想

1. 回溯法 (Backtracking):

  • 回溯法是一种通过递归去尝试所有可能的解,并在每次递归中做出选择、回溯的策略。
  • 在这道题中,我们需要通过回溯法来生成字符串的所有可能分割方式,并判断每个分割的子串是否为回文。

2. 分割与判断:

  • 首先,我们从字符串的第一个字符开始,依次检查从第一个字符到当前字符构成的子串是否为回文。
  • 如果当前子串是回文串,就可以继续尝试从这个子串的结尾位置向后继续分割剩下的部分。
  • 如果遍历完所有字符并且成功将字符串分割为回文子串(即字符串遍历完时,所有分割都是回文),就将这种分割方案保存起来。

3. 递归与回溯:

  • backtrack 方法是递归函数,用来从当前字符开始向后尝试不同的分割方法。
  • 每次找到一个回文串后,将其加入当前的结果列表 (currentList),然后递归处理剩下的部分。
  • 当递归到字符串结尾(即 start == s.length()),说明找到了一种合法的分割方式,这时将当前的分割方式保存到最终结果 result 中。
  • 当回溯返回时,撤销之前的选择,即将最后加入的回文串从列表中移除 (currentList.remove(currentList.size() - 1)),从而继续寻找其他可能的分割方案。

4. 判断回文串:

  • isPalindrome 方法中,通过双指针(从字符串两端向中间遍历)来判断某个子串是否是回文。
  • 只要发现左右两端字符不相等,就可以确定该子串不是回文,立即返回 false,否则继续判断直到中间。

代码执行过程(以 "aab" 为例):

  • 输入字符串 s = "aab"
  • 第一次递归从第一个字符开始,先检查子串 "a" 是否为回文,发现是回文,于是将 "a" 放入当前的分割列表,然后递归处理剩下的子串 "ab"
  • 在处理 "ab" 时,首先检查 "a",也是回文,于是继续递归处理 "b"。发现 "b" 也是回文,递归结束,得到一种分割方案 ["a", "a", "b"]
  • 回溯后,移除最后的 "b",然后继续尝试检查 "ab",发现不是回文,无法进行分割。
  • 继续回溯到最外层,移除 "a",然后尝试检查前两个字符 "aa",发现是回文,于是递归处理剩下的 "b",得到另一种分割方案 ["aa", "b"]
  • 递归结束,最终返回所有的分割结果。

复杂度分析:

  • 时间复杂度: 最坏情况下,每个子串都可能是回文,所以需要遍历所有可能的分割方式,时间复杂度大致为 O(n * 2^n),其中 n 是字符串的长度。
  • 空间复杂度: 由于递归深度取决于字符串的长度,因此空间复杂度为 O(n)。

总结:

这个算法通过回溯法,递归地生成所有可能的子串分割,并通过逐个判断子串是否为回文来过滤合法的分割方案。

java solution

java 复制代码
class Solution {
    public List<List<String>> partition(String s) {
        //result包含所有可能的回文分割方案
        List<List<String>> result = new ArrayList<>();
        //currentList代表某一种可能的回文分割方案
        List<String> currentList = new ArrayList<>();
        backtrack(result, currentList, s, 0);
        return result;
    }
    private void backtrack(List<List<String>> result, List<String> currentList, String s, int start) {
        if(start == s.length()) {
            result.add(new ArrayList<>(currentList));
            return; //这里必须return,递归终止条件
        }
        for(int i = start; i < s.length(); ++i) {
            if(isPalindrome(s, start, i)) {
                currentList.add(s.substring(start, i + 1)); //添加了一个回文子串,currentList.size()增加1
                backtrack(result, currentList, s, i + 1);
                currentList.remove(currentList.size() - 1); //撤销上个回文子串的选择
            }
        }

    }
    private boolean isPalindrome(String s, int low, int high) {
        while(low < high) {
            if(s.charAt(low) != s.charAt(high)) {
                return false;
            }
            low++;//注意更新左右指针!!
            high--;
        }
        return true;
    }
}
相关推荐
爱编程— 的小李9 分钟前
有序序列合并(c语言)
c语言·算法
云卓SKYDROID10 分钟前
无人机反步滑膜控制算法!
算法·无人机·知识科普·云卓科技·反步滑膜控制算法
云卓科技10 分钟前
无人机之自动控制原理篇
科技·算法·目标检测·机器人·无人机
云卓科技12 分钟前
无人机之集群控制方法篇
科技·算法·无人机·交互·制造
混迹网络的权某13 分钟前
每天一道C语言精选编程题之求数字的每⼀位之和
c语言·开发语言·考研·算法·改行学it·1024程序员节
lida200316 分钟前
无人机救援系统简单解读
linux·无人机·openipc·wfb-ng
Curry_Math17 分钟前
LeetCode 热题 100之链表3
算法·leetcode·链表
hn小菜鸡3 小时前
LeetCode 2058.找出临界点之间的最小和最大距离
算法·leetcode·职场和发展
liuyang-neu3 小时前
力扣 简单 70.爬楼梯
java·算法·leetcode
IronmanJay3 小时前
【LeetCode每日一题】——862.和至少为 K 的最短子数组
数据结构·算法·leetcode·前缀和·双端队列·1024程序员节·和至少为 k 的最短子数组