7.6分割回文串(LC131-M)

算法:

有很多分割结果,按照for循环去做肯定做不来

这个时候就要想到回溯!那就要画树!

画树

分割的画树过程其实和组合很像。

例如对于字符串aab:

  • 组合问题:选取一个a之后,在ab中再去选取第二个,选取a之后b中再选取第三个.....。
  • 切割问题:切割一个a之后,在ab中再去切割第二段,切割a之后在b再切割第三段.....。

回溯三部曲:

1.确定返回值和参数

返回值:void

参数:

string s 题目自带的

int startindex 确定每次递归从哪个字符开始切割

2.确定终止条件

切割到字符串最后,就是终止

startindex就是切割线:

startindex >= s.length()

并且要收集结果

3.单层递归逻辑:

子串怎么表示的?

答:[startindex, i]

i是这样定义的:

for (int i = startIndex; i < s.length(); i++)

收集结果:

若子串是回文(要定义一个新的函数,判断子串是否为回文),

将子串add入path,收集

若不是回文,continue,跳出该递归

递归:

注意切割过的位置,不能重复切割,所以,backtracking(s, i + 1); 传入下一层的起始位置为i + 1

backtracking (s, i+1)

回溯:

弹出本次已经添加的子串

path.removeLast()

判断回文子串

最后我们看一下回文子串要如何判断了,判断一个字符串是否是回文。

可以使用双指针法,一个指针从前向后,一个指针从后向前,如果前后指针所指向的元素是相等的,就是回文字符串了。

调试过程:

第一次调试:

复制代码
class Solution {
    //全局变量path和result
    List<List<String>> result = new LinkedList<>();
    List<String> path = new LinkedList<>();
    public List<List<String>> partition(String s) {
    backtracking (s, 0);
    return result;

    }
    void backtracking (String s, int startindex){
    //终止条件,收集结果
    if (startindex >= s.length()){
        result.add(new LinkedList (path));
        return;
    }
    //单层递归逻辑
    //判断子串是否为回文
    if (isplalindrome (s, startindex, i)){
        //若是,加入path
        path.add (s[startindex, i]);
    }
    else {continue;}
    //递归
    backtracking (s, i+1);
    //回溯
    path.removeLast();

}
    //判断回文plalindrome,左闭右闭
    boolean isplalindrome (String s, int start, int end){
    //双指针法
    for (int i, int j; i <= s.length(), j >=i; i++, j--){
        if (s[i] == s[j]) return true;
        return false;
    }

    }
}

原因:

1.path.add (s[startindex, i]);` 这一行存在语法错误。想要将子串添加到 `path` 列表中。为了修正这个问题,应该使用 `substring` 方法而不是方括号。修正后的代码应该是:path.add(s.substring(startIndex, i + 1));

在Java中,方括号主要用于数组的索引访问,而不用于提取子串(方括号是适用于python的,java不能用)。

对于字符串提取子串,可以使用**`substring`** 方法,该方法接受起始索引和结束索引作为参数,以提取指定范围内的子串。[左闭右开)

复制代码
String str = "Hello, World!";  
String sub = str.substring(startIndex, endIndex);  

在这里,`str` 是要提取子串的字符串,`startIndex` 是子串的起始索引,`endIndex` 是子串的结束索引(不包括在内)。提取的子串将包括从**`startIndex`** 到**`endIndex-1`**的字符。

因此,在您的代码中,`path.add(s.substring(startIndex, i + 1));` 将会提取**`s`** 字符串中从**`startIndex`** 到**`i`** (包括**`i`** )的子串,并将其添加到**`path`**列表中。

2.`isPalindrome` 方法中的for循环存在几个语法错误。看起来您想要在for循环中声明和初始化多个变量,但是语法是不正确的。让我们进行以下更正:

复制代码
for (int i = start, j = end; i <= j; i++, j--) {  
    // ... (代码的其余部分)  
}  

在 Java 中,当在 for 循环中声明多个变量时,不需要在每个变量前都加上 `int`

在 for 循环的初始化部分,只需要在第一个变量声明前加上类型,而后续的变量声明则只需要写变量名和初始值即可。

修改后:

原因:单层递归时忘记加for循环了

第二次调试:

原因:

string不能用方括号

应改为:

复制代码
s.charAt(i) == s.charAt(j)

第三次调试:

原因:把字符串本身也输出了。

主要问题在判断回文的逻辑上

判断是否为xxx,一定要先判错!有错即错!

当发现不是回文,就要立刻false;有不对的就不往下遍历了。一旦我们找到了一个不同的字符对,我们就可以确定这个字符串不是回文,因此可以立即返回 `false` 。这样可以提前结束检查,因为一旦发现不匹配,就不需要继续向后检查。

我原来判断的是,先判断前后是否相等,若相等,则true。

假设字符串是 "abca"。如果我们在检查第一个和最后一个字符相等时就提前返回 `true` ,那么我们会错误地认为 "abca" 是一个回文字符串,因为我们没有检查中间的字符。而且,当我们找到不同的字符时,就无法及时结束检查,而需要继续检查下去,这会降低算法的效率。

正确代码:

复制代码
class Solution {
    //全局变量path和result
    List<List<String>> result = new LinkedList<>();
    List<String> path = new LinkedList<>();
    public List<List<String>> partition(String s) {
    backtracking (s, 0);
    return result;

    }
    void backtracking (String s, int startindex){
    //终止条件,收集结果
    if (startindex >= s.length()){
        result.add(new LinkedList (path));
        return;
    }
    //单层递归逻辑
    //判断子串是否为回文
    for (int i=startindex; i<s.length();i++){ 
    if (isplalindrome (s, startindex, i)){
        //若是,加入path
        path.add(s.substring(startindex, i+1));
    }
    else {continue;}
    //递归
    backtracking (s, i+1);
    //回溯
    path.removeLast();
    }
   

}
    //判断回文plalindrome,左闭右闭
    boolean isplalindrome (String s, int start, int end){
    //双指针法
   for (int i=start, j=end; j >=i; i++, j--)
    {
        if (s.charAt(i) != s.charAt(j)) return false;   
    }
    return true;
    }
}

时间空间复杂度:

相关推荐
森焱森13 分钟前
水下航行器外形分类详解
c语言·单片机·算法·架构·无人机
QuantumStack2 小时前
【C++ 真题】P1104 生日
开发语言·c++·算法
写个博客3 小时前
暑假算法日记第一天
算法
绿皮的猪猪侠3 小时前
算法笔记上机训练实战指南刷题
笔记·算法·pta·上机·浙大
hie988943 小时前
MATLAB锂离子电池伪二维(P2D)模型实现
人工智能·算法·matlab
杰克尼4 小时前
BM5 合并k个已排序的链表
数据结构·算法·链表
.30-06Springfield4 小时前
决策树(Decision tree)算法详解(ID3、C4.5、CART)
人工智能·python·算法·决策树·机器学习
我不是哆啦A梦4 小时前
破解风电运维“百模大战”困局,机械版ChatGPT诞生?
运维·人工智能·python·算法·chatgpt
xiaolang_8616_wjl4 小时前
c++文字游戏_闯关打怪
开发语言·数据结构·c++·算法·c++20
small_wh1te_coder5 小时前
硬件嵌入式学习路线大总结(一):C语言与linux。内功心法——从入门到精通,彻底打通你的任督二脉!
linux·c语言·汇编·嵌入式硬件·算法·c