回溯算法之分割问题 leetcode分割回文串、复原ip地址

目录

131.分割回文串

93.复原ip地址


 131.分割回文串

题目:给你一个字符串 s,请你将s分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。回文串 是正着读和反着读都一样的字符串。

思路:分割问题和组合问题有相似之处,一个是选数,一个是选分割线。

class Solution {
    List> res=new ArrayList<>();
    List path=new ArrayList<>();
    String s;
    public List> partition(String s) {
        this.s=s;
        traceback(0);
        return res;
    }
    public void traceback(int start){
        //因为只有是回文字符串的时候才会回溯i+1,
        //所以start超过长度,说明一定找到了一组结果
        if(start>=s.length()){
            res.add(new ArrayList(path));
            return;
        }
        //!!标准的回溯找所有分割方法
        for(int i=start;i
93.复原ip地址

题目:

回溯算法之分割问题 leetcode分割回文串、复原ip地址_第1张图片

思路:和上一个题一样,也是分割。有一些小点不同,还有一些写的时候的错误记录,都标到代码里面了。

class Solution {
    List res=new ArrayList<>();
    StringBuilder sb=new StringBuilder();
    String s;
    public List restoreIpAddresses(String s) {
        if(s.length()<4 || s.length()>12)return res;
        this.s=s;
        traceback(0,0);
        return res;
    }

    //分割次数相比上题有限制,所以多了一个参数n记录分割次数
    public void traceback(int start,int n){
        //!!!这里多一个n==4,是为了防止n<4的时候也返回结果。
        if(start>=s.length()&&n==4){
            res.add(sb.deleteCharAt(sb.length()-1).toString());
            sb.append('.');//!!!!
            //错误记录1
            //这个是为了防止回溯sb的时候,删除的个数确定,多删的补回来凑数
            //!!!!!
            return;
        }
        for(int i=start;i3 || s.length()==0)return false;
        if(s.length()>1 && s.charAt(0)=='0')return false;
        //错误记录2
        //!!!!!这个一定是'0',不能是0
        if(Integer.parseInt(s)>255)return false;
        return true;
    }
}

卡哥的java代码 主要看最后,回溯时sb删除的那行


class Solution {
    List result = new ArrayList();
    StringBuilder stringBuilder = new StringBuilder();

    public List restoreIpAddresses(String s) {
        restoreIpAddressesHandler(s, 0, 0);
        return result;
    }

    // number表示stringbuilder中ip段的数量
    public void restoreIpAddressesHandler(String s, int start, int number) {
        // 如果start等于s的长度并且ip段的数量是4,则加入结果集,并返回
        if (start == s.length() && number == 4) {
            result.add(stringBuilder.toString());
            return;
        }
        // 如果start等于s的长度但是ip段的数量不为4,或者ip段的数量为4但是start小于s的长度,则直接返回
        if (start == s.length() || number == 4) {
            return;
        }
        // 剪枝:ip段的长度最大是3,并且ip段处于[0,255]
        for (int i = start; i < s.length() && i - start < 3 && Integer.parseInt(s.substring(start, i + 1)) >= 0
             && Integer.parseInt(s.substring(start, i + 1)) <= 255; i++) {
            // 如果ip段的长度大于1,并且第一位为0的话,continue
            if (i + 1 - start > 1 && s.charAt(start) - '0' == 0) {
                continue;
            }
            stringBuilder.append(s.substring(start, i + 1));
            // 当stringBuilder里的网段数量小于3时,才会加点;如果等于3,说明已经有3段了,最后一段不需要再加点
            if (number < 3) {
                stringBuilder.append(".");
            }
            number++;
            restoreIpAddressesHandler(s, i + 1, number);
            number--;
            // 删除当前stringBuilder最后一个网段,注意考虑点的数量的问题
            stringBuilder.delete(start + number, i + number + 2);
        }
    }
}

关于回溯时sb删除之前增加的网段。

我是倒数一个一个删,并且最后一个后面也加了点,保证数量不出错。

卡哥后面的java代码使用delete函数,确定前后索引。但是仍然存在最后一个网段少点,删除数量不同的问题,他这个索引i+number+2在最后一个字段会超过字符长度。

但是他的代码没有报错是为什么?

点到stringbuilder的delete函数源码看来一下:

回溯算法之分割问题 leetcode分割回文串、复原ip地址_第2张图片

可以看到:delete函数的第二个参数如果超过了sb的长度并不会报错,而是会让end=count

你可能感兴趣的:(数据结构与算法,leetcode,算法,数据结构,java)