回溯算法之切割问题

字符串的分割方案(LC的第131题)

题目描述:给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回 s 所有可能的分割方案。

示例: 输入: "aab" 输出: [ ["aa","b"], ["a","a","b"] ]

思路:这道题的难点在于如何切割,由于要求出所有可能的切割方案,因此要用到穷举法,但是仅仅用for循环极难实现(不知道字符串的长度,回文子串的长度也未知)。回溯法天然的可以遍历到任意长度的子串,在对其进行判断,在这里借用Carl代码随想录的图,具体过程如下:

我们可以看到在横向遍历中,变化的一直是要截取的子串的终止位置,而纵向遍历变的却是要截取字串的起始位置,因此当算法结束可以访问到字符串的所有子串。核心代码如下:

private void backTracking(String s, int startIndex) {
        //如果起始位置大于s的大小,说明找到了一组分割方案
        if (startIndex >= s.length()) {
            lists.add(new ArrayList(deque));
            return;
        }
        for (int i = startIndex; i < s.length(); i++) {
            //如果是回文子串,则记录
            if (isPalindrome(s, startIndex, i)) {
                String str = s.substring(startIndex, i + 1);
                deque.addLast(str);
            } else {
                continue;
            }
            //起始位置后移,保证不重复
            backTracking(s, i + 1);
            deque.removeLast();
        }
    }
    //判断是否是回文串
    private boolean isPalindrome(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;
    }

总结:在回溯算法的切割问题中,一定要注意切割的位置,递归的终止条件,横向遍历和纵向遍历的所代表的含义,在本题中,树的一条分支,即纵向遍历是一中切割方案,在一个集合中,横向遍历代表的是不同的切割方案,在不同的集合中。

切割问题的关键在于如何切割,确定好切割点就问题就容易很多,其他的就是一些条件判断和优化方面的问题,例如复原IP地址(LC的第93题),这题的切割方案与上诉类似,只是在题意基础上加了一些优化,进行了剪枝。

最后关于何时选回溯算法的一些理解:回溯主要可以解决一些组合、排列、子集等等类似的问题,若问题已知子串或集合的大小,如求子串的长度为2的集合,当然可以用for,若不知,如上面求回文的题,它的集合大小是未知的,集合中串的长度都是不同的,在这种情况下不太可能用for来实现,而回溯是可以遍历到所有的子集或子串。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值