当前位置: 首页 > news >正文

元素全排列问题的新思路(DFS,递归,计数器)

目录

前言

1,普通DFS实现1~n的元素全排列

2,计数器+DFS实现重复元素全排列

总结


前言

        我们之前看到的全排列问题的解法都是通过交换法达到的,去重的效果也是通过判断当前元素前是否有相同元素来实现,今天我们带来一个全新的思路,使我们直接进行深度优先搜索+一个计数器就可以实现,不用交换。


1,普通DFS实现1~n的元素全排列

 我们先一步一步来,先从1~n不重复的开始:

 假如说我们现在的n是3,则有以下排列组合:

        

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

仔细观察思考一下,我们列举这些排列组合的时候,是不是我们先固定了一个数字为基准,之后把剩下的数字进行全排列呢?那再继续往下说,我们在把剩下的数字全排列的时候,是不是也会跟前面一样,以一个数字为基准呢?我们推理一下:

第一次:
固定 1 1 ? ?       在2 3里面选固定21 2 ?    在3里面选固定31 2 3 排列出来了

以此类推,我们发现这样刚好适合使用递归和回溯算法来实现,我们在排列出来之后跳出递归,之后进行回溯,位数作为我们的参数,理解一下代码:

#include <iostream>using namespace std;int num[11], mark[11], n;void dfs(int p) {if (p == n + 1) {for (int i = 1; i <= n; i++) {cout << num[i] << ' ';}cout << endl;return;}for (int i = 1; i <= n; i++) {if (mark[i] == 0) {num[p] = i;mark[i] = 1;dfs(p + 1);mark[i] = 0;}}
}int main() {cin >> n;dfs(1);return 0;
}

这里我们使用一个mark数组来记录这个数字有没有在上一层递归中已经被选择过。

但是当我们输入的是自定义数组且有重复元素的时候,这个方法就失效了。

2,计数器+DFS实现重复元素全排列

我们设想,如果说我们给出一个有重复元素的数组  1 2 2 1,它的重复排列是因为什么?答案是如果以数值为判断标准,他们两个其实并没有区别,如果是交换法,那么以下标为判断标准,第一个2跟第二个2下标虽不同,但是如果与第一个交换,答案还是一样的。所以我们找另一种规律,那就是数量。我们发现这个数组中每种数字的数量是不一样的,这样的话我们每次判断这个数字用没用完就可以了:

void dfs(int p) {if (p == a.size()) { // 位数到了for (int t : a) {cout << t << ' ';}cout << endl;return;}for (int t : num) {if (cot[t] > 0) { // 判断是否要用这个数纯靠计数器a[p] = t;cot[t]--;dfs(p + 1);cot[t]++; // 回溯}}}

dfs函数就是这样,当我们使用了一个数字之后,计数器就减去1,回溯时加上1,但是它是怎么完成去重的呢?

这里如果我们直接使用输入时的数据进行递归,那结果是会有重复的,因为在我们回溯的时候,计数器的个数回拨了,但是这个时候循环的元素里又会有一个相同的元素,例如:

1 2 2 dfs时第一次:1 通过 计数器-- 进入递归 1 ? ?
1 不通过 2 通过 计数器-- 进入递归 1 2 ? 
1 不同过 2 通过 计数器-- 跳出递归 1 2 2

对的我没写错,其实第三个2没用上,因为我们其实只需要数字的种类就可以了,但是继续就会出现重复:

1 2 2 dfs时第一次:最外层递归 ? ? ?
1 通过 计数器-- 进入递归 1 ? ? 
1 不通过 2 通过 计数器-- 进入递归 1 2 ?  
1 不同过 2 通过 计数器-- 跳出递归 1 2 2回溯1次到了1 ? ?的时候,此时最外层递归还是1,里面的一层第一个 1 和 2已经用掉了,回溯了一次所以计数器的次数还剩一次,此时循环再次到2,不过是第三个2,但是因为回溯过,所以1 2 2再次出现,造成重复。接下来跳出递归后,再回溯了一次,回到了第二层递归,第二层递归循环结束回到了最外层,计数器归到2,最外层开始了2开头.........之后就是一样的剧本

我们通过分析递归了解了是遍历数组时的重复元素造成了结果的重复,而且其实我们依靠计数器的话也不需要这些重复的数据,只要一开始统计一下个数就好。

这样的话我们输入之后把数组过滤一下,1221过滤成12,只记录种类:

// 统计各个数字的个数for (int i = 0; i < a.size(); i++) {cin >> n;cot[n]++;}// 每个数字只添加一个for (int i = 0; i < cot.size(); i++) {if (cot[i] > 0) {num.push_back(i);}}sort(num.begin(), num.end());

先排个序可以确保结果也是有序的。

之后我们汇总一下看看整体代码:

//
// Created by 33058 on 2023-09-18.
//
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;vector<int> num, cot(10), a(3);void dfs(int p) {if (p == a.size()) { // 位数到了for (int t : a) {cout << t << ' ';}cout << endl;return;}for (int t : num) {if (cot[t] > 0) { // 判断是否要用这个数纯靠计数器a[p] = t;cot[t]--;dfs(p + 1);cot[t]++; // 回溯}}}int main() {int n;// 统计各个数字的个数for (int i = 0; i < a.size(); i++) {cin >> n;cot[n]++;}// 每个数字只添加一个for (int i = 0; i < cot.size(); i++) {if (cot[i] > 0) {num.push_back(i);}}sort(num.begin(), num.end());dfs(0);return 0;
}

这个是确位数 a 在     1<= a <= 3, 数字n在      0 <= a < 10之间的,开数组的时候10和3可以进行n位的推广。

要注意递归的出口一定是a.size()而不是num.size()因为num只记录了数字的种类,a才是真正的3位数!!

总结

至此全部的内容就结束了,大家可以仔细的理解代码,一步一步剖析递归的过程,从位数少的开始,这样也就好理解了。

相关文章:

元素全排列问题的新思路(DFS,递归,计数器)

目录 前言 1&#xff0c;普通DFS实现1~n的元素全排列 2&#xff0c;计数器DFS实现重复元素全排列 总结 前言 我们之前看到的全排列问题的解法都是通过交换法达到的&#xff0c;去重的效果也是通过判断当前元素前是否有相同元素来实现&#xff0c;今天我们带来一个全新的思路…...

机器学习 day35(决策树)

决策树 上图的数据集是一个特征值X采用分类值&#xff0c;即只取几个离散值&#xff0c;同时也是一个二元分类任务&#xff0c;即标签Y只有两个值 上图为之前数据集对应的决策树&#xff0c;最顶层的节点称为根节点&#xff0c;椭圆形节点称为决策节点&#xff0c;矩形节点称…...

小程序引入vant-Weapp保姆级教程及安装过程的问题解决

小知识&#xff0c;大挑战&#xff01;本文正在参与“程序员必备小知识”创作活动。 本文同时参与 「掘力星计划」&#xff0c;赢取创作大礼包&#xff0c;挑战创作激励金 当你想在小程序里引入vant时&#xff0c;第一步&#xff1a;打开官方文档&#xff0c;第二步&#xff…...

LeetCode 周赛上分之旅 #45 精妙的 O(lgn) 扫描算法与树上 DP 问题

⭐️ 本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架&#xff0c;你的思考越抽象&#xff0c;它能覆盖的问题域就越广&#xff0c;理解难度…...

JavaScript-DOM实战案例

一、window定时器 1.window定时器方法 有时我们并不想立即执行一个函数&#xff0c;而是等待特定一段时间之后再执行&#xff0c;我们称之为“计划调用&#xff08;scheduling a call&#xff09;”。 目前有两种方式可以实现&#xff1a; setTimeout 允许我们将函数推迟到一…...

STM32 学习笔记1:STM32简介

1 概述 STM32&#xff0c;从字面上来理解&#xff0c;ST 是意法半导体&#xff0c;M 是 Microelectronics 的缩写&#xff0c;32 表示 32 位&#xff0c;合起来理解&#xff0c;STM32 就是 ST 公司开发的 32 位微控制器。是一款基于 ARM 公司推出的基于 ARMv7 架构的 32 位 Co…...

Hadoop-Hbase

1. Hbase安装 1.1 安装zookeeper、 hbase 解压至/opt/soft&#xff0c;并分别改名 配置环境变量并source生效 #ZK export ZOOKEEPER_HOME/opt/soft/zk345 export PATH$ZOOKEEPER_HOME/bin:$PATH #HBASE_HOME export HBASE_HOME/opt/soft/hbase235 export PATH$HBASE_HOME/b…...

关于不停机发布新版本程序的方式

“不停机发布新版本程序”&#xff0c;暂且这么称呼吧&#xff0c;其实就是所说的滚动发布、灰度发布、金丝雀发布和蓝绿发布。 之所以会总结性地提一下这几个概念&#xff0c;主要是本次出门游历&#xff0c;流浪到了乌兰察布市四王子旗&#xff0c;在这儿遇上了个有趣儿的家伙…...

MeterSphere压测,出现HttpHostConnectException

现象&#xff1a;MeterSphere更换压力机后&#xff0c;压测出现出现HttpHostConnectException 解决方案&#xff1a; net.ipv4.tcp_tw_reuse默认是0或者2&#xff0c;更改为1 net.ipv4.tcp_tw_reuse&#xff0c;表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连…...

cherry-pick

要将dev分支的某次提交给master分支&#xff0c;可以使用以下命令&#xff1a; 1. 切换到dev分支&#xff1a;git checkout dev 2. 查看提交历史&#xff0c;找到要提交给master的某次提交的commit hash&#xff08;假设为 <commit_hash>&#xff09; 3. 切换到master…...

opencv形状目标检测

1.圆形检测 OpenCV图像处理中“找圆技术”的使用-图像处理-双翌视觉OpenCV图像处理中“找圆技术”的使用,图像处理,双翌视觉https://www.shuangyi-tech.com/news_224.htmlopencv 找圆心得&#xff0c;模板匹配比霍夫圆心好用 - 知乎1 相比较霍夫找直线算法&#xff0c; 霍夫找…...

k8s中无法获取到nginx-ingress的客户端真实ip地址x-forwarded-for

1.查看阿里云的nginx-ingress配置文档https://help.aliyun.com/document_detail/42205.html 容器K8s配置方案 如果您的服务部署在K8s上&#xff0c;K8s会将真实的客户端IP记录在X-Original-Forwarded-For字段中&#xff0c;并将WAF回源地址记录在X-Forwarded-For字段中。您需要…...

MySQL(4)索引实践(2)

一、分页优化 limit 1000 10&#xff0c; 其实不是只查询出10条记录&#xff0c;mysql底层会查询出1100条&#xff0c;然后舍去前1000条 所以&#xff0c;随着页的增多&#xff0c;查询效率会降低 1、可以使用取范围的方式比如id>1000 方式优化 2、使用关联查询优化&#xf…...

Kafka【命令行操作】

Kafka 命令行操作 Kafka 主要包括三大部分&#xff1a;生产者、主题分区节点、消费者。 1、Topic 命令行操作 也就是我们 kafka 下的脚本 kafka-topics.sh 的相关操作。 常用命令行操作 参数 描述 --bootstrap-server <String: server toconnect to> 连接的Kafka …...

springboot配置注入增强(二)属性注入的原理

一 原理 1 配置的存储 springboot在启动的时候会后构建一个org.springframework.core.env.Environment类型的对象&#xff0c;这个对象就是用于存储配置&#xff0c;如图springboot会在启动的最开始创建一个Environment对象 这个webApplicationType的枚举是在new SpringAppli…...

Android 使用Camera1实现相机预览、拍照、录像

1. 前言 本文介绍如何从零开始&#xff0c;在Android中实现Camera1的接入&#xff0c;并在文末提供Camera1Manager工具类&#xff0c;可以用于快速接入Camera1。 Android Camera1 API虽然已经被Google废弃&#xff0c;但有些场景下不得不使用。 并且Camera1返回的帧数据是NV21…...

2024字节跳动校招面试真题汇总及其解答(四)

12.Java的类加载机制 Java的类加载机制是指将描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机制。 类的加载过程分为以下五个阶段: 加载:将Class文件从磁盘读入内存,并…...

网页的快捷方式打开自动全屏--Chrome、Firefox 浏览器相关设置

Firefox 的全屏方式与 Chrome 不同&#xff0c;Chrome 自带全屏模式以及APP模式&#xff0c;通过简单的参数即可设置&#xff0c;而Firefox暂时么有这个功能&#xff0c;Firefox 的全屏功能可以通过全屏插件实现。 全屏模式下&#xff0c;按 F11 不会退出全屏&#xff0c;鼠标…...

LabVIEW使用ModbusTCP协议构建分布式测量系统

LabVIEW使用ModbusTCP协议构建分布式测量系统 分布式测量系统主要用于监控远程物体。这种系统允许对系统用户获得的数据进行全面的数据收集、处理、存储和组织访问。它们可能包括许多不同类型的传感器。 在任何具有互联网接入的个人计算机上运行的软件都会发送来自传感器的测…...

unity学习第1天

本身也具有一些unity知识&#xff0c;包括Eidtor界面使用、Shader效果实现、性能分析&#xff0c;但对C#、游戏逻辑不太清楚&#xff0c;这次想从开发者角度理解游戏&#xff0c;提高C#编程&#xff0c;从简单的unity游戏理解游戏逻辑&#xff0c;更好的为工作服务。 unity201…...

Spring Boot实现对文件进行压缩下载

在Web应用中&#xff0c;文件下载功能是一个常见的需求&#xff0c;特别是当你需要提供用户下载各种类型的文件时。本文将演示如何使用Spring Boot框架来实现一个简单而强大的文件下载功能。我们将创建一个RESTful API&#xff0c;通过该API&#xff0c;用户可以下载问价为ZIP压…...

Mac专用投屏工具AirServer 7 .27 for Mac中文免费激活版

AirServer 7 .27 for Mac中文免费激活版是一款Mac专用投屏工具&#xff0c;能够通过本地网络将音频、照片、视频以及支持AirPlay功能的第三方App&#xff0c;从 iOS 设备无线传送到 Mac 电脑的屏幕上&#xff0c;把Mac变成一个AirPlay终端的实用工具。 目前最新的AirServer 7.2…...

LabVIEW使用巴特沃兹低通滤波器过滤噪声

LabVIEW使用巴特沃兹低通滤波器过滤噪声 设备采集到的数据往往都有噪声&#xff0c;有时候这些数据要做判断使用&#xff0c;如果不处理往往会影响最终的结果。可以使用动态平滑&#xff0c;或者中值滤波等方法。这里介绍使用巴特沃斯低通滤波&#xff0c;也是非常方便的。 下…...

【Realtek sdk-3.4.14b】RTL8197FH-VG和RTL8812F自适应认证失败问题分析及修改

WiFi自适应认证介绍 WiFi 自适应可以理解为针对WiFi的产品,当有外部干扰信号通过,WiFi产品自动停止发出信号一段时间,以达到避让的目的。 问题描述 2.4G和5G WiFi自适应认证失败,信道停止发送信号时间过长,没有在规定时间内停止发包 2.4G截图 问题分析 根据实验室描述可以…...

SpringBoot 的版本、打包、Maven

一、SpringBoot 结构、集成 1.1、集成组件 Spring Core&#xff1a;Spring的核心组件&#xff0c;提供IOC、AOP等基础功能&#xff0c;是Spring全家桶的基础。 Spring Boot&#xff1a;一个基于Spring Framework的快速开发框架&#xff0c;可以快速创建独立的、生产级别的…...

不同类型程序的句柄研究

先做一个winform程序&#xff1b;随便放几个控件&#xff1b; 用窗口句柄查看工具看一下&#xff1b;form和上面的每个控件都有一个句柄&#xff1b; 然后看一下记事本&#xff1b;记事本一共包含三个控件&#xff0c;各自有句柄&#xff1b; 这工具的使用是把右下角图标拖到要…...

【Godot】解决游戏中的孤立/孤儿节点及分析器性能问题的分析处理

Godot 4.1 因为我在游戏中发现&#xff0c;越运行游戏变得越来越卡&#xff0c;当你使用 Node 节点中的 print_orphan_nodes() 方法打印信息的时候&#xff0c;会出现如下的孤儿节点信息 孤儿节点信息是以 节点实例ID - Stray Node: 节点名称(Type: 节点类型) 作为格式输出&a…...

国家网络安全宣传周知识竞赛活动小程序界面分享

国家网络安全宣传周知识竞赛活动小程序界面分享...

mysql的判断语句

if if 用于做条件判断&#xff0c;具体的语法结构如下&#xff0c;在 if 条件判断的结构中&#xff0c; ELSE IF 结构可以有多个&#xff0c;也可以没有。 ELSE 结构可以有&#xff0c;也可以没有。 IF 条件1 THEN ..... ELSEIF 条件2 THEN -- 可选 ..... ELSE -- 可选 .....…...

ArcGIS Maps SDK for JavaScript系列之四:添加自定义底图

目录 Basemap类介绍Basemap类的常用属性Basemap类的常用方法 使用Basemap添加自定义底图引用Basemap引用切片图层创建一个新的Basemap对象将自定义图层应用到地图视图中引入并创建Camera对象引入并创建SceneView对象 Basemap类介绍 Basemap类是ArcGIS Maps SDK for JavaScript…...

龙岩天宫山简介概况/免费的关键词优化工具

1)drawcall是什么,降低drawcall对性能调优的意义 面试题: drawcall是什么? (1)我们的游戏,提交给GPU来绘制; (2)drawcall就是: 我们的整个场景里面,分几个批次提交给显卡绘制,整个就是drawcall (3)100个物体需要绘制,分多少次批次提交给我们的GPU,整个…...

wordpress首页文章摘要/seo工程师招聘

1、WHERE字句的查询条件里有不等于号&#xff08;WHERE column!...&#xff09;&#xff0c;MYSQL将无法使用索引2、类似地&#xff0c;如果WHERE字句的查询条件里使用了函数&#xff08;如&#xff1a;WHERE DAY(column)...&#xff09;&#xff0c;MYSQL将无法使用索引3、在J…...

新开发网站/网络优化软件有哪些

可以对模型的查询和写入操作进行封装&#xff0c;例如&#xff1a;namespace appindexmodel;use thinkModel;class User extends Model{protected function scopeThinkphp($query){$query->where("name","thinkphp")->field("id,name");}p…...

四川城乡建设官方网站/关键词点击价格查询

课程目标&#xff1a; ① 在Servlet中懂得ServletContext HttpSession 以及HttpServletRequest之间的关系 ② 懂得怎样使用它们 概念介绍&#xff1a; 1. [共同点]不管对象的作用域怎样&#xff0c;共享变量和获得变量的 方法都是一致的 –setAttribute(“varName”,obj); –ge…...

wordpress 删除表/国产搜什么关键词最好看

本来8号可以过来的&#xff0c;结果because 家home事&#xff0c;不得已晚来了三天。全当报知遇之恩&#xff0c;一天顶一年的了。三年后&#xff0c;再说。三年死合同。 MySQL数据库基础学习&#xff0c; 之前work 用的SqlServer&#xff0c;new company 用的MySQL&#xff0…...

自己电脑做网站服务器系统/品牌策划与推广方案

全新日志思路...