回溯算法习题其二-Java【力扣】【算法学习day.16】

前言

###我做这类文档一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非常非常高滴!!!


习题

1.非递增子序列

题目链接: 491. 非递减子序列 - 力扣(LeetCode)

题面:

基本分析: 回溯暴力,可以维护一个set进行一些小剪枝

代码:

java 复制代码
class Solution {

    List<List<Integer>> res = new ArrayList<>();
    
    public List<List<Integer>> findSubsequences(int[] nums) {

        dfs(nums, -1, new ArrayList<>());
        return res;
    }

    private void dfs(int[] nums, int idx, List<Integer> curList) {
  
        if (curList.size() > 1) {
            res.add(new ArrayList<>(curList));
        }


        Set<Integer> set = new HashSet<>();
        for (int i = idx + 1; i < nums.length; i++) {
        
            if (set.contains(nums[i])) { 
                continue;
            }
            set.add(nums[i]);
        
            if (idx == -1 || nums[i] >= nums[idx]) {
                curList.add(nums[i]);
                dfs(nums, i, curList);
                curList.remove(curList.size() - 1);
            }
        }
    }
}

2.全排列

题目链接: 46. 全排列 - 力扣(LeetCode)

题面:

**基本分析:**在上一题的基础上维护一个数组来记录元素是否被使用

代码:

java 复制代码
class Solution {
    List<List<Integer>> list = new ArrayList<>();
    int len;
    public List<List<Integer>> permute(int[] nums) {
        len = nums.length-1;
        List<Integer> stack = new ArrayList<>();
        int[] arr = new int[len+1];
        recursion(nums,stack,arr);
        return list;
    }

    public void recursion(int[] nums,List<Integer> stack,int[] arr){
        if(stack.size()==len+1){
            list.add(new ArrayList<>(stack));
        }
        for(int i = 0;i<=len;i++){
            if(arr[i]==0){
                arr[i]=1;
                stack.add(nums[i]);
                recursion(nums,stack,arr);
                arr[i]=0;
                stack.remove(stack.size()-1);
            }
        }
    }
}

3.全排列II

题目链接: 47. 全排列 II - 力扣(LeetCode)

题面:

**基本分析:**元素重复导致重复答案,利用set去重

代码:

java 复制代码
class Solution {
    Set<List<Integer>> list = new HashSet<>();
    int len;
    public List<List<Integer>> permuteUnique(int[] nums) {
        len = nums.length-1;
        List<Integer> stack = new ArrayList<>();
        int[] arr = new int[len+1];
        recursion(nums,stack,arr);
        return new ArrayList<>(list);
    }
    public void recursion(int[] nums,List<Integer> stack,int[] arr){
        if(stack.size()==len+1){
            list.add(new ArrayList<>(stack));
        }
        for(int i = 0;i<=len;i++){
            if(arr[i]==0){
                arr[i]=1;
                stack.add(nums[i]);
                recursion(nums,stack,arr);
                arr[i]=0;
                stack.remove(stack.size()-1);
            }
        }
    }
}

4.重新安排行程

题目链接: 332. 重新安排行程 - 力扣(LeetCode)

题面:

基本分析: 对list排序和回溯暴力会超时最后一个样例 ,但是排序必不可少,参照下面这位的做法:

代码:

java 复制代码
class Solution {
    List<String> ans = new ArrayList<>();
    Map<String, TreeMap<String, Integer>> map = new HashMap<>();

    public List<String> findItinerary(List<List<String>> tickets) {
        for (List<String> list : tickets) {
            String start = list.get(0);
            TreeMap<String, Integer> tmap = map.getOrDefault(start, new TreeMap<>());
            String end = list.get(1);
            int sum = tmap.getOrDefault(end, 0) + 1;
            tmap.put(end, sum);
            map.put(start, tmap);
        }
        ans.add("JFK");
        try {
            recursion(tickets.size() + 1);
        } catch (RuntimeException e) {
        }
        System.out.println(tickets.size());
        System.out.println(ans.size());
        return ans;
    }

    public void recursion(int n) {
        if (ans.size() == n)throw new RuntimeException();
        String start = ans.getLast();
        if(map.containsKey(start)){
            for (Map.Entry<String, Integer> entry : map.get(start).entrySet()) {
            int count = entry.getValue();
            if (count > 0) {
                ans.add(entry.getKey());
                entry.setValue(count - 1);
                recursion(n);
                entry.setValue(count);
                ans.removeLast();
            }
        }
        }
    }
}

后言

上面是回溯算法的基本概念和部分习题,下一篇会讲解回溯算法的其他相关力扣习题,希望有所帮助,一同进步,共勉!

相关推荐
快乐是一切5 分钟前
PDF底层格式之水印解析与去除机制分析
前端·数据结构
泉城老铁12 分钟前
springboot实现对接poi 导出excel折线图
java·spring boot·后端
递归不收敛29 分钟前
吴恩达机器学习课程(PyTorch 适配)学习笔记:3.4 强化学习
pytorch·学习·机器学习
金銀銅鐵30 分钟前
[Java] 如何自动生成简单的 Mermaid 类图
java·后端
StarPrayers.32 分钟前
卷积层(Convolutional Layer)学习笔记
人工智能·笔记·深度学习·学习·机器学习
纵横八荒43 分钟前
Java基础加强13-集合框架、Stream流
java·开发语言
MHJ_1 小时前
Multi-Metric Integration(多指标集成)
数据结构
能不能别报错1 小时前
K8s学习笔记(十五) pause容器与init容器
笔记·学习·kubernetes
稚辉君.MCA_P8_Java1 小时前
kafka解决了什么问题?mmap 和sendfile
java·spring boot·分布式·kafka·kubernetes
乄bluefox1 小时前
保姆级docker部署nacos集群
java·docker·容器