五、回溯算法-算法总结

news2024/9/28 0:21:26

文章目录

  • 五、回溯算法
    • 5.1 背景
    • 5.2 模板
    • 5.3 集合类
      • 5.3.1 子集
      • 5.3.2 子集2
    • 5.4 排列类
      • 5.4.1 全排列
      • 5.4.2 全排列2
    • 5.5 组合类
      • 5.5.1 组合总和
      • 5.5.2 电话号码的字母组合

五、回溯算法

5.1 背景

回溯法(backtrack)常用于遍历列表所有子集,是 DFS 深度搜索一种,一般用于全排列,穷尽所有可能,遍历的过程实际上是一个决策树的遍历过程。时间复杂度一般 O(N!),它不像动态规划存在重叠子问题可以优化,回溯算法就是纯暴力穷举,复杂度一般都很高。

5.2 模板

result = []
func backtrack(选择列表,路径):
    if 满足结束条件:
        result.add(路径)
        return
    for 选择 in 选择列表:
        做选择
        backtrack(选择列表,路径)
        撤销选择

核心就是从选择列表里做一个选择,然后一直递归往下搜索答案,如果遇到路径不通,就返回来撤销这次选择。

5.3 集合类

5.3.1 子集

78. 子集
在这里插入图片描述

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        // 构建保存结果的List
        List<List<Integer>> result = new ArrayList<>();
        // 用于保存中间结果的List
        List<Integer> temp = new ArrayList<>();
        backTrack(temp, nums, 0, result);
        return result;

    }
// nums 给定的集合
// pos 下次添加到集合中的元素位置索引
// subSet 临时结果集合(每次需要复制保存)
// result 最终结果
    private void backTrack(List<Integer> temp, int[] nums, int pos, List<List<Integer>> result){
        // 将当前结果直接复制到结果List中
        result.add(new ArrayList<>(temp));
        for(int i = pos;i<nums.length;i++){
            // 选择、处理结果、再撤销选择
            temp.add(nums[i]); // 确定当前选择
            backTrack(temp,nums,i+1,result); // 在nums[i]的基础上作出之后的选择
            temp.remove(temp.size()-1); // 移除当前选择
        }
    }
}

5.3.2 子集2

90. 子集 II
在这里插入图片描述

class Solution {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        // 创建用于保存结果的List
        List<List<Integer>> result = new ArrayList<>();
        // 创建用于保存中间结果的List
        List<Integer> temp = new ArrayList<>();
        // 排序整数数组
        Arrays.sort(nums);
        backTrack(nums, 0, temp,result);
        return result;
    }

    private void backTrack(int[] nums, int pos, List<Integer> temp, List<List<Integer>> result){
        result.add(new ArrayList(temp));
        for(int i = pos;i<nums.length;i++){
            if(i != pos && nums[i-1] == nums[i]){ // 去除后一个重复选择
                continue;
            }
            temp.add(nums[i]); // 作选择
            backTrack(nums, i+1, temp, result);// 在当前选择下的后续选择
            temp.remove(temp.size()-1); // 撤销当前选择
        }
    }
}

5.4 排列类

5.4.1 全排列

46. 全排列
在这里插入图片描述

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> temp = new ArrayList<>();
        boolean[] isVisited = new boolean[nums.length];
        permute(nums, isVisited, result, temp);
        return result;
    }

    /**
    nums: 原始数据
    isVisited: 保存已访问过的信息
    result:保存结果
    temp:保存过程中的中间结果
     */
    private void permute(int[] nums, boolean[] isVisited, List<List<Integer>> result, List<Integer> temp){
        int l = nums.length;
        if(temp.size() == l){ // 终止条件
            result.add(new ArrayList<>(temp)); // 注意此处需使用复制操作的赋值
            return;
        }

        // 遍历可选择的情况
        for(int i = 0;i<l;i++){
            // 排除已经选择过的情况
            if(isVisited[i]){
               continue; 
            }
            temp.add(nums[i]); // 选择情况
            isVisited[i] = true; // 并记录已经访问过
            permute(nums, isVisited, result, temp);
            // 撤销当前选择
            temp.remove(temp.size()-1);
            isVisited[i] = false; // 并记录未访问过
        }
    }
}

5.4.2 全排列2

全排列 II
在这里插入图片描述

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> temp = new ArrayList<>();
        boolean[] isVisited = new boolean[nums.length];
        // 排序nums
        Arrays.sort(nums);
        permuteUnique(nums, isVisited, temp, result);
        return result;
    }

    private void permuteUnique(int[] nums, boolean[] isVisited, List<Integer> temp, List<List<Integer>> result){
        int l = nums.length;
        if(temp.size() == l){ // 终止条件
            result.add(new ArrayList<>(temp));
            return;
        }
        for(int i = 0;i<l;i++){
            // 条件一:访问过
            // 条件二:重复情况
            if(isVisited[i]){
                continue;
            }

            // 上一个元素和当前相同,并且没有访问过就跳过
            if (i != 0 && nums[i] == nums[i-1] && !isVisited[i-1]) {
                continue;
            }

            temp.add(nums[i]); // 做出选择
            isVisited[i] = true; //设置访问

            permuteUnique(nums, isVisited, temp, result);
            temp.remove(temp.size()-1);
            isVisited[i] = false;
        }
    }
}

5.5 组合类

5.5.1 组合总和

39. 组合总和
在这里插入图片描述

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> temp = new ArrayList<>();
        combinationSum(candidates, target, temp, 0, 0, result);
        return result;
    }

    /**
    candidates: 候选数组
    target: 目标值
    temp: 保存过程中的中间结果
    sum: 记录temp中的数据总和
    pos: 定位当前情况位置
    result: 保存结果
    
     */
    private void combinationSum(int[] candidates, int target, List<Integer> temp, int sum, int pos, List<List<Integer>> result){
    
        if(sum == target){ // 终止条件
            result.add(new ArrayList<>(temp)); // 记录组合结果
            return;
        }

        // 遍历所有情况
        for(int i = pos;i<candidates.length;i++){
            if(sum + candidates[i] > target){ // 若超过目标值则去除当前情况
                continue;
            }
            temp.add(candidates[i]); // 做出选择
            combinationSum(candidates, target, temp, sum+candidates[i], i, result); // 在当前选择的基础上做出下一步选择
            temp.remove(temp.size()-1); // 剔除当前情况
        }
    }
}

5.5.2 电话号码的字母组合

在这里插入图片描述

17. 电话号码的字母组合

class Solution {
    public List<String> letterCombinations(String digits) {
        if(digits.equals("")){
            return new ArrayList<>();
        }
        // 保存各数字对应的字母集
        Map<Character, String> map = new HashMap<>();
        map.put('2',"abc");
        map.put('3',"def");
        map.put('4',"ghi");
        map.put('5',"jkl");
        map.put('6',"mno");
        map.put('7',"pqrs");
        map.put('8',"tuv");
        map.put('9',"wxyz");

        List<String> result = new ArrayList<>();
        letterCombinations(digits, 0, new StringBuffer(), result, map);
        return result;
    }

    /**
    digits:原数字数组
    n:指定当前的位置
    sb: 保存中间结果
    result: 保存最终的结果
    map: 数字到字母的映射
     */
    private void letterCombinations(String digits, int pos, StringBuffer sb, List<String> result, Map<Character, String> map){
        if(pos == digits.length()){ // 终止条件
            result.add(new String(sb));
            return;
        }

        // 遍历所有情况
        for(char c:map.get(digits.charAt(pos)).toCharArray()){
            sb.append(c); // 做出选择
            letterCombinations(digits, n+1, sb, result, map); // 在当前情况下作下一步选择
            // 撤销选择
            sb.deleteCharAt(sb.length()-1);
        }
        
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2137193.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenAI草莓正式发布,命名o1

一、相关介绍 当地时间 9 月 12 日&#xff0c;OpenAI 推出全新模型 o1&#xff0c;它是该公司计划推出的一系列“推理”模型中的首个&#xff0c;也就是此前业内传闻许久的“Strawberry&#xff08;草莓&#xff09;”项目。 据悉&#xff0c;o1 模型在众多任务中能够比人类更…

LabVIEW机动车动态制动性能校准系统

机动车动态制动性能测试系统通过高精度的硬件设备与LabVIEW软件的紧密配合&#xff0c;实现了对机动车制动性能的精确校准与评估。系统不仅提高了测试的精确性和效率&#xff0c;而且具备良好的用户交互界面&#xff0c;使得操作更加简便、直观。 项目背景 随着机动车辆数量的…

C++:类和对象全解

C&#xff1a;类和对象全解 一、类的定义和初始化&#xff08;一&#xff09;类的定义1、类的成员变量&#xff08;1&#xff09;成员变量&#xff08;2&#xff09;成员函数 2、实例化对象&#xff08;1&#xff09;采用普通构造函数&#xff08;2&#xff09;采用初始化列表 …

MySQL数据的增删改查(二)

目录 约束 非空约束&#xff08;NOT NULL&#xff09; 唯一约束&#xff08;UNIQUE&#xff09; 默认值约束&#xff08;DEFAULT&#xff09; 主键约束&#xff08;PRIMARY KEY&#xff09; 外键约束&#xff08;FOREIGN KEY&#xff09; 检查约束&#xff08;CHECK&…

LabVIEW机械产品几何精度质检系统

随着制造业的发展&#xff0c;对产品质量的要求越来越高&#xff0c;机械产品的几何精度成为衡量其品质的重要指标。为了提高检测效率和精度&#xff0c;开发了一套基于LabVIEW的几何精度质检系统&#xff0c;该系统不仅可以自动化地进行几何尺寸的测量&#xff0c;而且能实时分…

kafka 之 本地部署单机版

安装JDK 查看你选择的版本需要安装哪一个版本的jdk 网址 下载 JDK下载 注&#xff1a;如果网页不允许下载&#xff0c;使用wget命令下载即可&#xff0c;下载之后安装。 建议使用rpm安装&#xff0c;之后使用 update-alternatives --config java 控制当前环境使用Java的版…

SpringBoot 处理 @KafkaListener 消息

消息监听容器 1、KafkaMessageListenerContainer 由spring提供用于监听以及拉取消息&#xff0c;并将这些消息按指定格式转换后交给由KafkaListener注解的方法处理&#xff0c;相当于一个消费者&#xff1b; 看看其整体代码结构&#xff1a; 可以发现其入口方法为doStart(),…

2024-2025年最全的计算机软件毕业设计选题大全

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

通过API接口获取数据:高效、灵活的数据交互之道

在数字化时代&#xff0c;数据已成为企业最宝贵的资产之一。企业和开发者对于数据的获取、处理和分析的需求日益增长。API&#xff08;应用程序编程接口&#xff09;接口作为连接不同系统和应用程序的桥梁&#xff0c;提供了一种高效、灵活的方式来获取和交换数据。本文将探讨为…

rust + bevy 实现小游戏 打包成wasm放在浏览器环境运行

游戏界面 代码地址 github WASM运行 rustup target install wasm32-unknown-unknown cargo install wasm-server-runner cargo run --target wasm32-unknown-unknowncargo install wasm-bindgen-cli cargo build --release --target wasm32-unknown-unknown wasm-bindgen --…

工厂模式(二):工厂方法模式

一、概念 工厂方法模式&#xff08;Factory Method&#xff09;&#xff0c;定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。从而使得系统更加灵活。客户端可以通过调用工厂方法来创建所需的产品&#xff0c;而不必…

Linux进程间通信——管道实现实战;深度学习,探索管道接口、特性、情况

前言&#xff1a;本节内容仍是管道&#xff0c; 上节内容我们学习了管道的原理。 这节内容将在原理的基础上&#xff0c; 讲解管道的编程&#xff0c; 特性&#xff0c;应用等等。 下面开始我们的学习吧。 ps&#xff1a;本节内容需要了解一些管道的原理&#xff0c; 希望友友们…

AIGC-初体验

线性分类 提问&#xff0c;目的试图让AI自动线性分类 A类&#xff1a;(10,21),&#xff08;3,7&#xff09;,(9,20&#xff09;(121,242) B类&#xff1a;(3,9),(5,11),(70,212),(11,34) 根据线性关系分类 请问 (100,300)&#xff0c;&#xff08;100&#xff0c;201&#xff…

nacos和eureka的区别详细讲解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; Nacos 和 Eureka 是两种服务注册与发现的组件&#xff0c;它们在微服务架构中扮演重要角色。两者虽然都是为了解决服务发现的问题&#xff0c;但在功能特性、架构、设计理念等方面有很多不同。以下是详细的…

【期末复习】软件项目管理

前言&#xff1a; 关于软件项目管理这一科目的重要期末考点&#xff0c;希望对你有帮助。 目录 质量管理可能遇到的问题 软件项目质量管理 软件项目风险管理 进度 题1 题2 题3 成本 题1 题2 题3 质量管理可能遇到的问题 (1)没有制定质量管理计划&#xff1a; (2)…

JMeter测试工具的简单了解

Apache JMeter 是一款开源的测试工具&#xff0c;主要用于对软件的性能进行测试。它最初被设计用于测试Web应用&#xff0c;但随着时间的推移&#xff0c;它的功能已经扩展到了其他测试领域。 可以应用到的场景 性能测试&#xff1a;评估应用程序在不同负载下的表现。负载测试…

初学代码指南(软2耶)

首先&#xff0c;很高兴又和大家见面了&#xff0c;本文章仅是作者的自我总结&#xff0c;是给笔者看的&#xff0c;所以读者在阅读时请抱着参考的心态&#xff0c;如果觉得可以借鉴的可以稍微借鉴一下&#xff0c;如果觉得笔者写了一坨shi&#xff0c;可以随便喷俺。 一.IDE …

音视频开发常见的开源项目汇总

FFmpeg 地址&#xff1a;https://ffmpeg.org/介绍&#xff1a;FFmpeg 是一个非常强大的开源多媒体框架&#xff0c;它可以用来处理视频和音频文件。它支持多种格式的转换、编码、解码、转码、流处理等。FFmpeg 包括了 libavformat、libavcodec、libavutil、libswscale、libpos…

✨机器学习笔记(四)—— 逻辑回归、决策边界、过拟合、正则化

Course1-Week3: https://github.com/kaieye/2022-Machine-Learning-Specialization/tree/main/Supervised%20Machine%20Learning%20Regression%20and%20Classification/week3机器学习笔记&#xff08;四&#xff09; 1️⃣逻辑回归&#xff08;logistic regression&#xff09;…

[数据集][目标检测]疟疾恶性疟原虫物种目标检测数据集VOC+YOLO格式948张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;948 标注数量(xml文件个数)&#xff1a;948 标注数量(txt文件个数)&#xff1a;948 标注类别…