【算法】回溯算法

回溯算法

什么是回溯

人生无时不在选择。在选择的路口,你该如何抉择 .....

回溯: 是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

回溯,计算机算法,回溯法也称试探法,它的基本思想是:从问题的某一种状态(初始状态)出发,搜索从这种状态出发所能达到的所有“状态”,当一条路走到“尽头”的时候(不能再前进),再后退一步或若干步,从另一种可能“状态”出发,继续搜索,直到所有的“路径”(状态)都试探过。这种不断“前进”、不断“回溯”寻找解的方法,就称作“回溯法”。--百度百科

一个例子看回溯

给下图的图顶点进行三种颜色着色(红、黄、蓝)

要求:

  1. 每个顶点的颜色只能从红、黄、蓝中选一个种。

  2. 相邻的两种颜色不能为同一种颜色。

思考方式

暴力推测,查找各种可能...

image-20241020173912533

树型策略

暴力查找结果(从上向下[第n=1行开始],从左边开始):

  1. n=1,先取红,n=2取红

  1. [红、红、红], [红,红,黄],[红,红,蓝]; [红,黄, 红],[红,黄,黄],[红,黄,蓝];[红,蓝,红],[红,蓝,黄],[红,蓝,蓝]

  2. n=1, n=2取黄

  3. n=2, n=3,取蓝色

  1. 回溯到根节点,走n=1,取黄色

回溯的一般规律

我们可以针对以上的找色问题,给出以下的一般的解决方案。

  1. 初始化: 初始化变量

  2. 找一个合法值,通过遍历(+1/-1)选取所有的可能[可以认为是树的深度]

  3. 栈记录

  4. 递归调用

  5. 回溯已经使用的值

经典题目

全排列

题目

[力扣46] 46. 全排列 - 力扣(LeetCode)

题目描述

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

输入:nums = [1]
输出:[[1]]
解决方案

image-20241023202329664

提交模版
public List<List<Integer>> permute(int[] nums) { ​ }
参考实现
class Solution {
​
    private List<List<Integer>> list = new ArrayList<>();
    private Stack<Integer> stack = new Stack<>();
​
    public List<List<Integer>> permute(int[] nums) {
        boolean[] isUsed = new boolean[nums.length];
        dfs(nums, 0, isUsed);
        return list;
    }
​
    private void dfs(int[] nums, int depth, boolean[] isUsed) {
        if (depth == nums.length) {
            list.add(new ArrayList<>(stack));
            return;
        }
​
        for (int i = 0; i < nums.length; i++) {
            if (isUsed[i]) {
                continue;
            }
            stack.push(nums[i]);
            isUsed[i] = true;
            dfs(nums, depth + 1, isUsed);
            stack.pop();
            isUsed[i] = false;
        }
    }
}

全排列II

题目

[力扣47] 47. 全排列 II - 力扣(LeetCode)

题目描述

给定一个可包含重复数字的序列 nums按任意顺序 返回所有不重复的全排列。

示例 1:

输入:nums = {1,1,2}
输出:
{
 {1,1,2},
 {1,2,1},
 {2,1,1}
}

示例 2:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
解题思路
提交模版
public List<List<Integer>> permuteUnique(int[] nums) {   }
参考实现
class Solution {
  private final List<List<Integer>> list = new ArrayList<>();
    private final Stack<Integer> stack = new Stack<>();
    private final Set<List<Integer>> sets = new HashSet<>();
​
​
    public List<List<Integer>> permuteUnique(int[] nums) {
        boolean[] isUsed = new boolean[nums.length];
        dfs(nums, 0, isUsed);
        list.addAll(sets);
        return list;
    }
​
    /**
     * @param nums
     * @param depth  递归的深度,从底层开始到最后一层
     * @param isUsed 判断当前数据是否使用过
     */
    private void dfs(int[] nums, int depth, boolean[] isUsed) {
        if (depth == nums.length) {
            sets.add(new ArrayList<>(stack));
            return;
        }
​
        Set<Integer> set = new HashSet<>();//记录重复数据
        for (int i = 0; i < nums.length; i++) { //遍历数组
            //数据重复或者使用过则跳过当前数据
            if (isUsed[i] ) continue;
           // set.add(nums[i]); //记录选择的数据
          //  System.out.println("set-->" + set);
            stack.push(nums[i]);
            isUsed[i] = true;
            dfs(nums, depth + 1, isUsed);
            stack.pop();
            isUsed[i] = false;
        }
    }
}

子集问题

题目

[力扣78] 78. 子集 - 力扣(LeetCode)

题目描述

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]
输出:[[],[0]]
解题思路

创建策略树

我们会发现出现大量的无效操作数据。对策略树进行"剪枝"处理。

剪枝- 我们“剪掉”了不满足约束条件的搜索分支,避免许多无意义的尝试,从而提高了搜索效率。

提交模版
 public List<List<Integer>> subsets(int[] nums) { }
参考实现
class Solution {
    List<List<Integer>> list = new ArrayList<>();
    Stack<Integer> stack = new Stack<>();
​
    public List<List<Integer>> subsets(int[] nums) {
        dfs(nums, 0);
        return list;
    }
​
    private void dfs(int[] nums, int startIndex) {
​
        list.add(new ArrayList<>(stack));
        if (startIndex >= nums.length) {
            return;
        }
​
        for (int i = startIndex; i < nums.length; i++) {
            stack.push(nums[i]);
            dfs(nums, i + 1);
            stack.pop();
​
        }
    }
}

剪枝优化

class Solution {
    private final List<List<Integer>> list = new ArrayList<>();
    private final List<Integer> stack = new ArrayList<>();
​
    public List<List<Integer>> subsets(int[] nums) {
        boolean[] isUsed = new boolean[nums.length];
        dfs(nums, 0, isUsed);
        return list;
    }
​
    private void dfs(int[] nums, int startIndex, boolean[] isUsed) {
​
        list.add(new ArrayList<>(stack)); //记录扫描的所有节点
        for (int i = startIndex; i < nums.length; i++) {
            if (isUsed[i])
                continue;
            stack.add(nums[i]);
            isUsed[i] = true;
            dfs(nums, i + 1,isUsed);
            stack.remove(stack.size()-1);
            isUsed[i] = false;
​
        }
    }
}

子集II

题目

[力扣90] 90. 子集 II - 力扣(LeetCode)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图解JVM-1. JVM与Java体系结构

一、前言 在 Java 开发的广袤天地里&#xff0c;不少开发者都遭遇过令人头疼的状况。线上系统毫无征兆地卡死&#xff0c;陷入无法访问的僵局&#xff0c;甚至直接触发 OOM&#xff08;OutOfMemoryError&#xff0c;内存溢出错误&#xff09;&#xff1b;面对 JVM 的 GC&#…

深入浅出 Python Logging:从基础到进阶日志管理

在 Python 开发过程中&#xff0c;日志&#xff08;Logging&#xff09;是不可或缺的调试和监控工具。合理的日志管理不仅能帮助开发者快速定位问题&#xff0c;还能提供丰富的数据支持&#xff0c;让应用更具可观测性。本文将带你全面了解 Python logging 模块&#xff0c;涵盖…

设计模式15:中介者模式

系列总链接&#xff1a;《大话设计模式》学习记录_net 大话设计-CSDN博客 1.概述 中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为设计模式&#xff0c;旨在通过一个中介对象来封装一系列对象之间的交互方式&#xff0c;从而减少这些对象间的直接依赖。在该模式…

爬取网站内容转为markdown 和 html(通常模式)

我们遇到一些自己喜欢内容&#xff0c;想保存下来&#xff0c;手动复制粘贴很麻烦&#xff0c;我们使用 python 来爬取这些内容。 一、代码 downlod.py import os import requests from bs4 import BeautifulSoup from urllib.parse import urljoin# 目标网页&#xff08;可…

【Linux】命令操作、打jar包、项目部署

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;Xshell下载 1&#xff1a;镜像设置 二&#xff1a;阿里云设置镜像Ubuntu 三&#xf…

Unity合批处理优化内存序列帧播放动画

Unity合批处理序列帧优化内存 介绍图片导入到Unity中的处理Unity中图片设置处理Unity中图片裁剪 创建序列帧动画总结 介绍 这里是针对Unity序列帧动画的优化内容&#xff0c;将多个图片合批处理然后为了降低Unity的内存占用&#xff0c;但是相对的质量也会稍微降低。可自行进行…

day4 多连联表慢查询sql查询优化

1.Explain分析sql语句出现的字段是什么意思 id: 查询的序列号&#xff0c;表示查询中 select 子句或操作表的顺序。 如果 id 相同&#xff0c;则执行顺序从上到下。 如果 id 不同&#xff0c;如果是子查询&#xff0c;id 的值会递增&#xff0c;id 值越大优先级越高&#xff0c…

基于豆瓣2025电影数据可视化分析系统的设计与实现

✔️本项目旨在通过对豆瓣电影数据进行综合分析与可视化展示&#xff0c;构建一个基于Python的大数据可视化系统。通过数据爬取收集、清洗、分析豆瓣电影数据&#xff0c;我们提供了一个全面的电影信息平台&#xff0c;为用户提供深入了解电影产业趋势、影片评价与演员表现的工…

力扣高频sql 50题(基础版) :NULL, 表连接,子查询,case when和avg的结合

NULL的处理 nvl(字段,num) 和数字进行比较需要先使用nvl(字段,num)函数处理空值 思路: 没有被id 2 的客户推荐>> 过滤条件 referee_id !2 没有被id 2 的客户推荐>>被其他客户推荐, 但是也有可能没有被任何客户推荐>>NULL 考点: NULL是 不一个具体的数…

夜莺监控发布 v8.beta5 版本,优化 UI,新增接口认证方式便于鉴权

以防读者不了解夜莺&#xff0c;开头先做个介绍&#xff1a; 夜莺监控&#xff0c;英文名字 Nightingale&#xff0c;是一款侧重告警的监控类开源项目。类似 Grafana 的数据源集成方式&#xff0c;夜莺也是对接多种既有的数据源&#xff0c;不过 Grafana 侧重在可视化&#xff…

Python - 爬虫利器 - BeautifulSoup4常用 API

文章目录 前言BeautifulSoup4 简介主要特点&#xff1a;安装方式: 常用 API1. 创建 BeautifulSoup 对象2. 查找标签find(): 返回匹配的第一个元素find_all(): 返回所有匹配的元素列表select_one() & select(): CSS 选择器 3. 访问标签内容text 属性: 获取标签内纯文本get_t…

认识 ADB(Android Debug Bridge,Android SDK 中的一个工具)

一、ADB 概述 ADB&#xff0c;全称 Android Debug Bridge&#xff0c;是 Android SDK 中的一个工具 ADB 位于 Android SDK 下 platform-tools 目录中 ADB 起到调试桥的作用&#xff0c;ADB 可以让开发者通过 USB 连接安卓设备&#xff0c;并在电脑上执行各种命令&#xff0c;…

模拟解决哈希表冲突

目录 解决哈希表冲突原理&#xff1a; 模拟解决哈希表冲突代码&#xff1a; 负载因子&#xff1a; 动态扩容&#xff1a; 总结&#xff1a; HashMap和HashSet的总结&#xff1a; 解决哈希表冲突原理&#xff1a; 黑色代表一个数组&#xff0c;当 出现哈希冲突时&#xff0…

FPGA简介|结构、组成和应用

Field Programmable Gate Arrays&#xff08;FPGA&#xff0c;现场可编程逻辑门阵列&#xff09;&#xff0c;是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物&#xff0c; 是作为专用集成电路&#xff08;ASIC&#xff09;领域中的一种半定制电路而出现的&#xff0c…

【机器学习】超参数调优指南:交叉验证,网格搜索,混淆矩阵——基于鸢尾花与数字识别案例的深度解析

一、前言&#xff1a;为何要学交叉验证与网格搜索&#xff1f; 大家好&#xff01;在机器学习的道路上&#xff0c;我们经常面临一个难题&#xff1a;模型调参。比如在 KNN 算法中&#xff0c;选择多少个邻居&#xff08;n_neighbors&#xff09;直接影响预测效果。 • 蛮力猜…

UGUI RectTransform的SizeDelta属性

根据已知内容&#xff0c;SizeDelta offsetMax - offsetMin 1.锚点聚拢情况下 输出 那么此时SizeDelta就是UI元素的长宽大小 2. 锚点分散时 引用自此篇文章中的描述 揭秘&#xff01;anchoredPosition的几何意义&#xff01; SizeDelta offsetMax - offsetMin (rectMax…

51单片机入门_10_数码管动态显示(数字的使用;简单动态显示;指定值的数码管动态显示)

接上篇的数码管静态显示&#xff0c;以下是接上篇介绍到的动态显示的原理。 动态显示的特点是将所有位数码管的段选线并联在一起&#xff0c;由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选&#xff…

mybatis使用typeHandler实现类型转换

使用mybatis作为操作数据库的orm框架&#xff0c;操作基本数据类型时可以通过内置的类型处理器完成java数据类型和数据库类型的转换&#xff0c;但是对于扩展的数据类型要实现与数据库类型的转换就需要自定义类型转换器完成&#xff0c;比如某个实体类型存储到数据库&#xff0…

瑞萨RA-T系列芯片ADCGPT功能模块的配合使用

在马达或电源工程中&#xff0c;往往需要采集多路AD信号&#xff0c;且这些信号的优先级和采样时机不相同。本篇介绍在使用RA-T系列芯片建立马达或电源工程时&#xff0c;如何根据需求来设置主要功能模块ADC&GPT&#xff0c;包括采样通道打包和分组&#xff0c;GPT触发启动…

最新智能优化算法:牛优化( Ox Optimizer,OX)算法求解经典23个函数测试集,MATLAB代码

一、牛优化算法 牛优化&#xff08; OX Optimizer&#xff0c;OX&#xff09;算法由 AhmadK.AlHwaitat 与 andHussamN.Fakhouri于2024年提出&#xff0c;该算法的设计灵感来源于公牛的行为特性。公牛以其巨大的力量而闻名&#xff0c;能够承载沉重的负担并进行远距离运输。这种…