Leetcode刷题模板总结-回溯算法

Leetcode刷题模板总结-回溯算法

回溯算法是较为经典的几个算法之一,经典的问题有八皇后等,今天做leetcode发现一道经典的回溯问题,所以总结一下回溯问题的解题模板。此外做题过程中还发现一直困惑的一个点,即每一次回溯的状态都要new一个新的对象开销太大的问题,下面会仔细分析

Leetcode题目为面试题 08.07
在这里插入图片描述
题目很简单,就是需要列出几个字母的全排列,和八皇后或者2020年蓝桥杯省赛电子管的那道题相似,都是回溯的题目,所以这里给出回溯JAVA用递归实现的模板

//    List<Object> res = new ArrayList<>();
//    public void backtrack(路径, 可选列表) {
//        if (终止条件) {
//            加入 res;
//            return;
//        }
//        for (选择:选择列表) {
//            做出选择;
//            backtrack(路径, 选择列表);
//            撤销选择;
//        }
//    }

下面是未优化前的解答:

private List<String> result;
    public String[] permutation(String S) {
        result=new LinkedList<>();
        char[] arr=S.toCharArray();
        Set<Character> totalSet=new HashSet<>();
        for(char c:arr)     totalSet.add(c);
        track(totalSet,new LinkedList<>());
        return result.toArray(new String[result.size()]);
    }
    private void track(Set<Character> set,List<Character> list){
        if(set.isEmpty()){
            StringBuilder sb=new StringBuilder();
            for(char c:list){
                sb.append(c);
            }
            result.add(sb.toString());
            return;
        }
        
        for(char c : set){
            Set<Character> newSet=new HashSet<>(set);
            List<Character> newList=new LinkedList<>(list);
            newSet.remove(c);
            newList.add(c);
            track(newSet,newList);
        }
    }
解释解释一下大概的思路,核心的代码在track方法,两个参数分别是:

set:可以使用的char集合
list:已经排好的一个序列

track方法主要有两部分,第一部分if终止条件,用来将list中的字符拼成String并添加到全局变量上,第二部分遍历set集合,开始下一轮回溯。最终耗时排名5%,空间24%。

做完后反思了下,可以有以下几个优化的点

1、全局变量可以用一个String[] 变量,因为长度为全排列的个数,这个是固定的可以计算出来
2、用空间换了时间,for遍历的时候用set省去了不必要的遍历,但是结果证明这样性能并没有得到提升
3、(重点)每一次回溯遍历都new了set和list对象,非常占空间,且list和set操作也比数组耗时长

对于第三点,就是开头说的每一次回溯都要保留一次状态,开销太大的问题,后面翻了下题解,发现一个比较好的解决方案,可以不用多个set保存可以使用的字符,改成用一个全局的boolean[],list改成了StringBuilder,这么做比set和list要好的多
在这里插入图片描述
这里只截取了部分片段,题解中解决多个set开销太大的办法是用一个对象来保存状态,使用完之后要撤销该次操作,所以不会影响下一次遍历递归。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 二分法 5 1.1. 什么是二分查找 5 1.2. 如何识别二分法 5 1.3. 二分法模板 6 1.3.1. 模板一 6 1.3.1.1. 模板代码 6 1.3.1.2. 关键属性 7 1.3.1.3. 语法说明 7 1.3.1.4. Lc69:x的平方根 8 1.3.1.5. Lc374:猜数大小 9 1.3.1.6. Lc33:搜索旋转数组 11 1.3.2. 模板二 13 1.3.2.1. 模板代码 13 1.3.2.2. 关键属性 14 1.3.2.3. 语法说明 14 1.3.2.4. Lc278:第一个错误版本 14 1.3.2.5. Lc162:寻找峰值 16 1.3.2.6. Lc153:寻找旋转排序数组最小值 19 1.3.2.7. Lc154:寻找旋转排序数组最小值II 20 1.3.3. 模板三 22 1.3.3.1. 模板代码 22 1.3.3.2. 关键属性 23 1.3.3.3. 语法说明 23 1.3.3.4. LC-34:在排序数组中查找元素的第一个和最后一个 23 1.3.3.5. LC-658:找到K个最接近的元素 25 1.3.4. 小结 28 1.4. LeetCode中二分查找题目 29 2. 双指针 30 2.1. 快慢指针 31 2.1.1. 什么是快慢指针 31 2.1.2. 快慢指针模板 31 2.1.3. 快慢指针相关题目 32 2.1.3.1. LC-141:链表是否有环 32 2.1.3.2. LC-142:环形链表入口 34 2.1.3.3. LC-876:链表的中间节点 37 2.1.3.4. LC-287:寻找重复数 40 2.2. 滑动窗口 43 2.2.1. 什么是滑动窗口 43 2.1.4. 常见题型 44 2.1.5. 注意事项 45 2.1.6. 滑动窗口模板 45 2.1.7. 滑动窗口相关题目 46 2.1.7.1. LC-3:无重复字符的最长子串 47 2.1.7.2. LC-76:最小覆盖子串 49 2.1.7.3. LC-209:长度最小的子数组 54 2.1.7.4. LC-239:滑动窗口最大值 57 2.1.7.5. LC-395:至少有K个重复字符的最长子串 60 2.1.7.6. LC-567:字符串排列 62 2.1.7.7. LC-904:水果成篮 64 2.1.7.8. LC-424:替换后的最长重复字符 66 2.1.7.9. LC-713:乘积小于K的子数组 67 2.1.7.10. LC-992:K个不同整数的子数组 70 2.3. 左右指针 73 2.3.1. 模板 73 2.3.2. 相关题目 73 2.3.2.1. LC-76:删除倒数第N个节点 74 2.3.2.2. LC-61:旋转链表 76 2.3.2.3. LC-80:删除有序数组中的重复项 79 2.3.2.4. LC-86:分割链表 80 2.3.2.5. LC-438:找到字符串中所有字母的异位词 82 3. 模板 85 2.3.2.6. LC-76:删除倒数第N个节点 85

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值