【数据结构】回溯算法公式化解题 leetcode经典题目带刷:全排列、组合、子集

news2024/9/27 15:20:51

目录

    • 回溯算法
      • 一、什么是回溯算法
        • 1、基本思想:
        • 2、一般步骤:
      • 二、题目带练
        • 1、全排列
        • 2、组合
        • 3、子集
      • 三、公式总结

回溯算法

一、什么是回溯算法

回溯算法(Backtracking Algorithm)是一种解决组合问题排列问题选择问题等一类问题的常用算法。它通过尝试所有可能的选择来找到问题的解,当发现当前选择不符合要求时,就回溯到之前的状态,然后尝试其他的选择。

1、基本思想:

  1. 从问题的起始点开始,进行尝试,每次选择一个可能的路径。
  2. 如果发现当前选择无法达到解决问题的目标,就回退到上一个状态,尝试其他的选择。
  3. 不断地重复上述过程,直到找到解决问题的路径,或者遍历完所有可能的选择。

2、一般步骤:

  1. 确定问题的解空间和约束条件。
  2. 从解空间中选择一个可能的选择,进入下一步。
  3. 判断当前选择是否符合约束条件,如果符合,继续深入尝试下一步;如果不符合,回退到上一步。
  4. 重复上述步骤,直到找到解,或者遍历完所有可能的选择。

二、题目带练

1、全排列

题目地址
在这里插入图片描述
分析
看到这道题的描述,不难想到,如果我们要找出所有的排列方式,就要遍历n次数组,每次选择一个不重复元素排列在上次循环选择的元素后面,那这就出现了一个问题怎么对一个数组遍历n次?

显然这是不太可能实现的,因为n是不确定的,但是我们可以换一种思路,通过深度来代表遍历次数,也就是我们常说的回溯算法。

根据题意,我们应当设递归出口为 当前递归的深度 == 数组的长度if(depth == nums.length),同时保存当前的排列方式到集合中。ans.add(new ArrayList<>(path));每次递归的过程中我们需要遍历一次数组for(int i = 0; i < nums.length; i++),判断当前的元素是否被使用过if(used[i]),如果没被使用那么就将其记录下来,并且标记为使用过,继续进入递归path.add(nums[i]); used[i] = true;。当这次递归结束时dfs(nums,depth + 1,used);,撤销当前元素的使用标记,并且移除记录的集合。path.remove(path.size() - 1); used[i] = false;

效果就是调用方法后,先选择元素1path.add(nums[0]); used[0] = true;,再次调用方法记录深度+1dfs(nums,depth + 1,used);,此时发现1已经被选择过了,开始选择2path.add(nums[1]); used[1] = true;,调用递归,深度+1dfs(nums,depth + 1,used);,同理1,2被标记为使用过的元素,继续选择3path.add(nums[2]); used[2] = true;,然后递归结束。这里会退回到深度为2的那次选择,因为2之后还有别的元素可以选择,选择3后发现只有2可以选了,首选项为1的递归结束,依次类推得到所有排列方式。
在这里插入图片描述

代码如下:

class Solution {
    public List<List<Integer>> ans = new ArrayList<>();
    public List<Integer> path = new ArrayList<>();
    public List<List<Integer>> permute(int[] nums) {
        boolean[] used = new boolean[nums.length];
        dfs(nums,0,used);
        return ans;
    }

    public void dfs(int[] nums,int depth,boolean[] used){
        if(depth == nums.length){
            ans.add(new ArrayList<>(path));
            return;
        }

        for(int i = 0; i < nums.length; i++){
            if(used[i]){
                continue;
            }
            path.add(nums[i]);
            used[i] = true;
            dfs(nums,depth + 1,used);
            path.remove(path.size() - 1);
            used[i] = false;
        }
    }
}

2、组合

题目地址
在这里插入图片描述
分析

这道题与全排列的区别在于,全排列需要全部选择,而这道题不一定要全部选择,并且每个组合只能有一次,所以面对这道题,我们不能按照和之前同样的思路去解,因为无法排除同样组合的组合顺序问题。

那么我们要如何作出改动呢?

其实很简单,我们只需要让每次循环的起始值变为当前的深度即可,同时也不需要判断是否使用过了,因为我们只会向后找,不会从前开始往后找了。

class Solution {
    List<Integer> temp = new ArrayList<Integer>();
    List<List<Integer>> ans = new ArrayList<List<Integer>>();

    public List<List<Integer>> combine(int n, int k) {
        dfs(1, n, k);
        return ans;
    }

    public void dfs(int depth, int n, int k) {
        if (temp.size() == k) {
            ans.add(new ArrayList<Integer>(temp));
            return;
        }
        for(int i = depth;i <= n;i++){
            temp.add(i);
            dfs(i + 1, n, k);
            temp.remove(temp.size() - 1);
        }
    }
}

3、子集

题目地址
在这里插入图片描述
分析

大家看这道题可能会发现,是不是和组合有点相似?区别在哪呢,区别在于子集的选择长度不一定是n,而是[0,n]

其实我们只需要每次回溯都记录一次结果就好了。

class Solution {
    List<Integer> list = new ArrayList<>();
    List<List<Integer>> result = new ArrayList<>();

    public List<List<Integer>> subsets(int[] nums) {
        dfs(0,nums);
        return result;
    }

    public void dfs(int current, int[] nums){
        result.add(new ArrayList<>(list));
        if(current == nums.length){
            return;
        }
        for(int i = current; i < nums.length; i++){
            list.add(nums[i]);
            dfs(i + 1, nums);
            list.remove(list.size() - 1);
        }
    }
}

三、公式总结

如果认真看完的朋友可以发现,对于这种基础的回溯题目,我们都可以通过循环+回溯来解决问题,只需要根据具体问题来更改我们的循环条件即可。

当然这么做不一定是最好的,还有许多可以优化的地方,只是说大部分情况可以通过这种循环的方式来解决问题。

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

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

相关文章

Python“牵手”淘宝商品详情数据采集方法,淘宝API申请步骤说明

淘宝平台API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范。 淘宝API接口是指通过编程的方式&#xff0c;让开发者能够通过HTTP协议直接访问淘宝平台的数据&#xff0c;包括商品信息、店铺信息、物流信息等&#xff0c;从而实现淘宝平台的数据开…

Android开发基础知识总结(一)初识安卓Android Studio

一.基础理论知识 1.Linux相当于是地基。 MIUI&#xff0c;EMUI等操作系统&#xff0c;是基于安卓的改版——且裁掉了一部分Google的服务。 &#xff08;鸿蒙虽然是改版&#xff0c;但和安卓的架构基本上一致&#xff09; 2.Kotlin和Java都是JVM语言&#xff0c;必须先复习好…

Python数据分析实战-给定JSON格式的数据提取所需字段并转换为DataFrame(附源码和实现效果)

实现功能 给定JSON格式的数据提取所需字段并转换为DataFrame 实现代码 import pandas as pd import json# 假设给定的JSON数据已经存储在data变量中 data [{"title": "Data Source Adapter for Excel Sheets","project_code_url": "htt…

Mac下Jmeter安装及基本使用

本篇文章只是简单的介绍下Jmeter的下载安装和最基本使用 1、初识Jmeter 前一段时间客户端app自测的过程中&#xff0c;有偶现请求某个接口返回数据为空的问题&#xff0c;领导让我循环100次请求这个接口&#xff0c;看看有没有结果为空的问题。听同事说有Jmeter的专业测试工具…

Java数据结构学习和源码阅读(线性数据结构)

线性数据结构 链表 LinkList 链表的数据结构 一组由节点组成的数据结构&#xff0c;每个元素指向下一个元素&#xff0c;是线性序列。 最简单的链表结构&#xff1a; 数据指针&#xff08;存放执行下一个节点的指针&#xff09; 不适合的场景&#xff1a; 需要循环遍历将…

【C++】 使用红黑树模拟实现STL中的map与set

文章目录 前言1. 对之前实现的红黑树进行一些补充和完善1.1 析构1.2 查找 2. STL源码中map和set的实现3. 改造红黑树封装map和set3.1 红黑树结构修改3.2 map、set的结构定义3.3 insert的封装3.4 insert测试3.5 发现问题并解决3.6 红黑树迭代器实现3.7 封装set和map的迭代器并测…

uniapp scroll-view横向滚动无效,scroll-view子元素flex布局不生效

要素排查&#xff1a; 1.scroll-x属性需要开启&#xff0c;官方类型是Boolean&#xff0c;实际字符串也行。 2scroll-view标签需要给予一个固定宽度&#xff0c;可以是百分百也可以是固定宽度或者100vw。 3.子元素需要设置display: inline-block&#xff08;行内块元素&#x…

国标GB28181视频平台EasyGBS通过对应密钥上传到其他平台展示的详细步骤来啦!

国标GB28181协议视频平台EasyGBS是基于国标GB28181协议的视频云服务平台&#xff0c;支持多路设备同时接入&#xff0c;并对多平台、多终端分发出RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。平台可提供视频监控直播、云端录像、云存储、检索回放、智能告警、语音对讲、平台级…

项目管理实战笔记:硬技能(下)

需求变更&#xff1a; pmp里面涉及需求变更的很多&#xff0c;尤其是CCB 对于CCB的需求变更&#xff0c;可能需要以下步骤&#xff1a; 1. 确定变更的原因和必要性&#xff1a;需要了解变更是因为业务需求的变化、技术方案的变更还是其他原因&#xff0c;以及变更是否是必要的…

内行才知道的新闻稿发布技巧,媒介盒子为你揭秘

不知道最近其他小伙伴有没有遇上以上说的一些情况&#xff0c;必须借助新闻稿发布达到营销推广的目的。 可是对于新闻稿发布这一块却不知道应该怎么办&#xff0c;尤其是新手上任&#xff0c;对于如何发布新闻稿是一头雾水。 新闻稿的发布是企业在公关传播中重要的一环&#…

如何将PDF文件转换为PPT文件?

如何将pdf转换成ppt&#xff1f;PDF文件作为常用的文件格式&#xff0c;不仅可以在教学过程中使用&#xff0c;还可以在营销展会、培训讲座等过程中使用。欧迪芬文件的使用&#xff0c;能够在一定程度上提升我们的办公效率。对于PDF文件来说&#xff0c;其中包含的元素非常多&a…

【算法刷题之数组篇(2)】

目录 1.leetcode-35. 搜索插入位置&#xff08;简单&#xff09;2.leetcode-74. 搜索二维矩阵&#xff08;中等&#xff09;3.leetcode-73. 矩阵置零&#xff08;中等&#xff09;4.leetcode-56. 合并区间&#xff08;中等&#xff09;5.leetcode-54. 螺旋矩阵&#xff08;中等…

水溶性试剂Hexynoic acid STP ester,炔酸STP酯,NHS酯的极好替代品

产品简介&#xff1a;炔酸STP酯是一种具有末端炔丙基和STP酯基的水溶性试剂。STP酯是在水性环境中进行偶联反应的传统N-羟基琥珀酰亚胺&#xff08;NHS&#xff09;酯的极好替代品。炔丙基通过铜催化的叠氮化物-炔烃点击化学与含叠氮化物的化合物或生物分子反应&#xff0c;产生…

leetcode303. 区域和检索 - 数组不可变(java)

前缀和数组的应用 区域和检索 - 数组不可变题目描述前缀和数组代码演示 区域和检索 - 数组不可变 难度 - 简单 原题链接 - 区域和检索 - 数组不可变 题目描述 给定一个整数数组 nums&#xff0c;处理以下类型的多个查询: 计算索引 left 和 right &#xff08;包含 left 和 righ…

解决运行在微信小程序中报[ app.json 文件内容错误] app.json: app.json 未找到(env: Windows,mp,1.05.2204

找到project.config.json文件夹 添加 "miniprogramRoot": "unpackage/dist/dev/mp-weixin/", 即可

发展全球电商业务,为什么首选Facebook Messenger电子商务?

Facebook Messenger电子商务就是使用Facebook的消息传递渠道Messenger来购买和销售产品或服务。通过将 Messenger与客户服务平台&#xff0c;例如SaleSmartly&#xff08;SS客服&#xff09;集成&#xff0c;企业可以利用渠道强大的消息传递功能为客户提供更加个性化和对话式的…

这个免费全景网站你知道吗,多篇教程教您如何创作全景作品

引言&#xff1a; 随着科技的不断进步&#xff0c;虚拟现实&#xff08;VR&#xff09;技术正逐渐融入我们的日常生活&#xff0c;为我们带来了没有过的沉浸式体验。其中&#xff0c;VR全景网站作为一种引领人们身临其境体验的创新方式&#xff0c;正在逐渐受到大众的关注。 蛙…

androidStudio或IDEA的通过gitBash打开插件

本人&#xff0c;一个资深的命令行&#xff0c;业余爱好者。常年直接vim&#xff0c;或者shell上服务器阅读代码。比较偏好使用GitBash来打开项目&#xff0c;进行git status&#xff0c;git diff&#xff0c;git add&#xff0c;commit等动作。 基于以上原因&#xff0c;本人开…

怎样通过本地电脑搭建SFTP服务器,并实现公网访问?

本地电脑搭建SFTP服务器&#xff0c;并实现公网访问 文章目录 本地电脑搭建SFTP服务器&#xff0c;并实现公网访问1. 搭建SFTP服务器1.1 下载 freesshd 服务器软件1.3 启动SFTP服务1.4 添加用户1.5 保存所有配置 2. 安装SFTP客户端FileZilla测试2.1 配置一个本地SFTP站点2.2 内…

SecureCRT 备份Button Bar中所有Button

一、前言 Button Bar功能可以保存一些常用命令避免重复输入&#xff0c;但是有时候secureCRT的button bar经常莫名其妙消失&#xff0c;重装系统或软件后&#xff0c;也都需要重新一个个添加Button&#xff0c;如果能备份就能减少这些费时间的操作 二、备份步骤 在面板Optio…