回溯算法与字符串的爱恨情仇

不久之前,我写过几篇数据结构与算法的内容,有关的是一些题目我自己做下来的心得体会。时隔多日,我现在记录下回溯算法

按照程序员carl的指导下,学会了回溯三部曲。在组合篇,我个人觉得还是能略微得心应手的,但在字符串篇时,感觉有些力不从心了,不过在一段时间的理解下,我掌握了比较简单的方式去刷字符串的题目。一下就以两道题目为主:

核心思想就是:先分割,再判断

这边的分割就是全部的分割情况,并且只看第一层的分割情况,绝不去想第二层的情况(人脑很难想出来)

题目一:分割回文串

链接:. - 力扣(LeetCode)

class Solution {
    List<List<String>> lists = new ArrayList<>();
    Deque<String> deque = new LinkedList<>();

    public List<List<String>> partition(String s) {
        backTracking(s, 0);
        return lists;
    }

    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++) {
            // 先切割
            String str = s.substring(startIndex, i + 1);
            // 如果是回文子串,则记录
            if (isPalindrome(str,0,str.length()-1)) {
                deque.addLast(str);
                // 起始位置后移,保证不重复
                backTracking(s, i + 1);
                deque.removeLast();
            } else {
                continue;
            }

        }
    }

    // 判断是否是回文串
public boolean isPalindrome(String s, int startIndex, int end) {
    while (startIndex < end) {
        if (s.charAt(startIndex) != s.charAt(end)) {
            return false;
        }
        startIndex++;
        end--;
    }
    return true;
}

}

这边为了时间更快先,就用了双指针法,不然直接将字符串反转reverse,与原来的进行比对,也能判断是否是回文串。

题目二:复原IP地址

链接:. - 力扣(LeetCode)

class Solution {
    public List<String> restoreIpAddresses(String s) {
        List<List<String>> res = new ArrayList<>();
        List<String> finalRes = new ArrayList<>();
        Deque<String> path = new ArrayDeque<>();
        backtracking(res, path, 0, s);
        for (int i = 0; i < res.size(); i++) {
            String tempPath = "";
            List<String> temp = new ArrayList<>(res.get(i));
            for (String string : temp) {
                if (tempPath.equals("")) {
                    tempPath = tempPath + string;
                } else {
                    tempPath = tempPath + "." + string;
                }
            }
            finalRes.add(tempPath);
        }

        return finalRes;
    }

    public void backtracking(List<List<String>> res, Deque<String> path, int startIndex, String s) {
//        终止条件
        if (startIndex >= s.length()&&path.size()==4) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = startIndex; i < s.length(); i++) {
//                先截取字符串
            String temp = s.substring(startIndex, i + 1);
            if (istest(temp) && path.size() < 4) {
                path.offer(temp);
                backtracking(res, path, i + 1, s);
                path.removeLast();
            }
        }

    }

    public boolean istest(String s) {
        int length = s.length();
        if (length > 3) {
            return false;
        }
        int i = Integer.parseInt(s);
        if (i > 255) {
            return false;
        }
        if (length >= 2 && s.charAt(0)=='0') {
            return false;
        }
        return true;
    }
}

还是传统方式,如果字符串难以在回溯过程中剔除最后一位,直接将切割下来的字符放入Deque中,后续再完成拼接。

总结:其实,做此类题目时,只要想着第一层的逻辑即可,只要第一层逻辑正确,后续很难出错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值