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

排列问题方法总结(递归+迭代)

递归

一、逐步生成结果法(无序)

#include<iostream>  
#include<vector>  
#include<string>
#include<algorithm>using namespace std;vector<string> GetChild(int n,int curIndex){vector<string> now;vector<string> cur;if (curIndex == 1) {  now.push_back("1");cur=now;return cur;}cur=GetChild(n, curIndex - 1);for (string temp : cur) {now.push_back(temp + to_string(curIndex));now.push_back(to_string(curIndex) + temp);for (int j = 1; j < temp.size(); j++) {now.push_back(temp.substr(0, j) + to_string(curIndex) + temp.substr(j));}}cur = now;return cur;
}int main(void) {int n,k;cin >> n>>k;// 获取子集vector<string>ans = GetChild(n,n); // 存放子集的数组//排序sort(ans.begin(), ans.end());// 输出子集个数int n_ = ans.size();cout << "子集个数:" << n_ << endl;// 输出子集  for (auto sub_set : ans) {cout << sub_set << endl;}cout<<endl;// 输出第k个子集cout << ans[k - 1];return 0;
}

这个代码主要就是讲的是逐步生成结果,然后它主要就是利用了一个递归的思想。

首先就是先假设我求出来了前 n -1 个数的排列,然后我作为老板我只需要去 排列 第 n 个数。它的排法一共有三种,首先就是可以把这个数插在这个排列的前面,也可以插在排列的后面。除此之外也可以插在这个排列的中间的任何一个空里面。

总的来说他主要就是将这个新的数插到一切可以插的空里面,然后记录即可。

对于递归出口,我们要设一个变量,用来代表我当前是对于第几个元素进行操作,当达到第一个元素时,那么就新建一个数组,然后将这个第一个元素放进去,代表我是一个数的排列,就是它本身。

但是这种方法求出来的排列并不是有序的,我们在最后输出结果的时候要记得对这个排列进行排序。(后面有已序的求法)

递归的思想前面也说过,它主要就是一种老板思维,就是我不需要去考虑一些细节上的东西,相当于把一些重复性的工作让员工去做,然后我只需要进行最后一步,或者说是特定的一步即可。然后注意初始条件。


二、基于交换的递归方法(交换完排序则是有序)

#include<iostream>  
#include<vector>  
#include<string>  
#include<algorithm>  using namespace std;vector<string> ans;void GetChild(string s, int n, int curIndex) {cout << string(curIndex, ' ') << "+-- " << s << endl; // 打印当前状态  if (curIndex == n) {ans.push_back(s);cout << string(curIndex, ' ') << "|   Found permutation: " << s << endl; // 指示找到的排列  return; // 退出递归  }for (int i = curIndex; i < n; i++) {swap(s[i], s[curIndex]);sort(s.begin() + curIndex + 1, s.end()); // 交换后,将curIndex之后的元素排序(保证字典序)GetChild(s, n, curIndex + 1);swap(s[i], s[curIndex]); // 还原交换  }cout << string(curIndex, ' ') << "+-- Exiting depth " << curIndex << ": " << s << endl; // 打印退出当前状态  }
int main(void) {int n;cin >> n;// 初始化字符串并排序  string s = "";for (int i = 1; i <= n; i++) {s += to_string(i);}GetChild(s, n, 0); // 生成所有排列  // 输出排列个数  int n_ = ans.size();cout << "排列个数:" << n_ << endl;// 输出所有排列  for (const auto& sub_set : ans) {cout << sub_set << endl;}return 0;
}

CurIndex 指的是当前元素的下标。递归操作时先交换i处和当前下标元素的位置,然后对后面的元素进行一个升序排序,就是字典序。

然后递归的调用这个函数,最后再还原交换。

当我的CurIndex 等于 n 的时候,相当于我从第一个元素遍历到第二个元素,然后 存入s 。(s在交换的过程中被改变,初始化为升序排列)


三、逐个交换大法(有序)

#include<iostream>  
#include<vector>  
#include<string>  
#include<algorithm>  using namespace std;vector<string> ans;
int cnt = 0;
int flag = 0;int Mcount(string s, char c) {int count = 0;for (int i = 0; i < s.size(); i++) {if (s[i] == c) {count++;}}return count;
}void GetChild(string s, string arr,int k) {if (flag == 1) {return;}if (s.size() == arr.size()) {cnt++;ans.push_back(s);if (cnt == k) {flag = 1;    }}for (int i = 0; i < arr.size(); i++) {char c = arr[i];if (Mcount(s,c) < Mcount(arr,c)) {GetChild(s + c, arr, k);}if (flag == 1) {return;}}
}
int main(void) {int n,k;cin >> n>>k;// 初始化字符串并排序  string s = "";for (int i = 1; i <= n; i++) {s += to_string(i);}GetChild("", s, k); // 生成所有排列  // 输出排列个数  int n_ = ans.size();cout << "排列个数:" << n_ << endl;// 输出所有排列  for (const auto& sub_set : ans) {cout << sub_set << endl;}cout << endl;cout<<ans[k-1]<<endl;return 0;
}

Mcount参数是用来记录当前元素在字符串中的个数。

Getchild 函数里面进行递归操作。

递归出口就是 s 的大小等于数组大小,然后记录这个数字里面字符串的数目,当它等于 k 的时候,我们就让递归函数退出。

然后基本的递归操作就是记录当前的字符,然后判断在当前排列和数组中该字符的个数。如果说当前字符串中,该字符个数小于数组中的话,就把当前字符加到我的当前s的后面,然后递归的去求。

这个是一个有序的递归方法。主要是因为对于元素的添加是有序的。

递归退出主要是利用一个 flag 标志,当满足条件的时候改变这个标志,然后在递归函数的出口前判断这个标志。


迭代:

逐步生成迭代大法:

#include<iostream>  
#include<vector>  
#include<string>
#include<algorithm>using namespace std;vector<string> GetChild(int n) {vector<string> cur;cur.push_back("1");for (int i = 2; i <= n; i++) {vector<string> now;for (string temp : cur) {now.push_back(temp + to_string(i));now.push_back(to_string(i) + temp);for (int j = 1; j < temp.size(); j++) {now.push_back(temp.substr(0, j) + to_string(i) + temp.substr(j));}}cur = now;}return cur;
}int main(void) {int n,k;cin >> n>>k;// 获取子集vector<string>ans = GetChild(n); // 存放子集的数组//排序sort(ans.begin(), ans.end());// 输出子集个数int n_ = ans.size();cout << "子集个数:" << n_ << endl;// 输出子集  for (auto sub_set : ans) {cout << sub_set << endl;}cout<<endl;// 输出第k个子集cout << ans[k - 1];return 0;
}

这个逐步生成的迭代大法其实和上面那个递归的逐步生成方法类似,它的思想也是一致的。首先我是建立一个字符串数组,然后先放入第一个元素,也就是1。

然后紧接着我遍历所有元素,对于当前的元素的话,它有三种可能的放置方式,首先是放在原有排列的前面,还有一种是放在排列后面,或者是插在这个排列的中间。总而言之它就是放在所有能放的位置.


利用排列性质的迭代算法:

#include<iostream>  
#include<vector>  
#include<algorithm>using namespace std;vector<vector<int>> GetChild(int n) {int row = n;vector<vector<int>> cur;for (int i = 0; i < row; i++) {vector<int> temp(n, 0);temp[i] = 1;cur.push_back(temp);}for (int i = 2; i <= n; i++) {vector<vector<int>> now;vector<int> temp;for (int j = 0; j < cur.size(); j++) {for (int k = 0; k < n; k++) {temp = cur[j];if (temp[k] == 0) {temp[k] = i;now.push_back(temp);}}}cur = now;}return cur;
}int main(void) {int n,k;cin >> n>>k;// 获取子集vector<vector<int>>ans = GetChild(n); // 存放子集的数组//排序sort(ans.begin(), ans.end());// 输出子集个数int n_ = ans.size();cout << "子集个数:" << n_ << endl;// 输出子集  for (auto sub_set : ans) {cout << "{ ";for (auto elem : sub_set) {cout << elem << " ";}cout << "}" << endl;}// 输出第k个子集for (auto elem : ans[k - 1]) {cout << elem;}return 0;
}

这个迭代法的主要思路就是按照顺序把对应的元素排在能排在第一个位置。

首先就是我要初始化一个二维数组,这个二维数组用矩阵的思维去看的话,它应当是一个单位矩阵,也就是在它主对角线上面一个元素都是1,然后就是这个矩阵里的1,分别代表1这个元素在第一个到第 n 个位置上的情况。

然后对于每一个其他元素,遍历当前的这个二维数组。然后对于每一个一维数组来说,我的第二个元素他能放在第一个位置是哪个?然后我将它放在这个位置上,然后依次类推第三个元素,它能放的第一个位置就是没有元素占领的位置,然后再把这个新的元素给它保存下来,最终就得到我们的结果。

这个方法其实也不是一个有序的,我们最后也要对它进行排序,然后这个方法其实是利用到排列的每个元素都有可能在每个位置上这样一种思想。

相关文章:

排列问题方法总结(递归+迭代)

递归 一、逐步生成结果法&#xff08;无序&#xff09; #include<iostream> #include<vector> #include<string> #include<algorithm>using namespace std;vector<string> GetChild(int n,int curIndex){vector<string> now;vector&…...

C#从入门到放弃

C#和.NET的区别 C# C#是一个编程语言 .NET .NET是一个在window下创建程序的框架 .NET框架不仅局限于C#,它还可以支持很多语言 .NET包括了2个组件&#xff0c;一个叫CLR(通用语言运行时)&#xff0c;另一个是用来构建程序的类库 CLR 用C写一个程序&#xff0c;在一台8688的机器…...

视频质量评价学习笔记

目录 MD VQA:大淘宝团队&#xff1a; ReIQA KVQ 视频质量评价学习笔记 MD VQA:大淘宝团队&#xff1a; https://github.com/kunyou99/MD-VQA_cvpr2023?tabreadme-ov-file ReIQA GitHub - avinabsaha/ReIQA: Official implementation for CVPR2023 Paper "Re-IQA : U…...

OpenCV、YOLO、VOC、COCO之间的关系和区别

OpenCV、YOLO、COCO 和 VOC 是计算机视觉和深度学习领域常见的几个名词&#xff0c;它们分别代表不同的工具、算法和数据集&#xff0c;之间有一些联系和区别。下面分别说明它们的定义、用途以及相互关系。 1. OpenCV&#xff08;Open Source Computer Vision Library&#xf…...

Pandas进行周期与时间戳转换

时间序列数据在数据分析和金融领域非常常见,处理这些数据时,通常会面临周期(Period)与时间戳(Timestamp)之间的转换需求。理解和掌握这种转换,对于时间序列数据的清洗、预处理以及进一步分析至关重要。Python 中的 pandas 库提供了一系列便捷的函数来帮助处理这些时间序…...

【GPTs】Get Simpsonized:一键变身趣味辛普森角色

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 &#x1f4af;GPTs指令&#x1f4af;前言&#x1f4af;Get Simpsonized主要功能适用场景优点缺点使用方式 &#x1f4af;小结 &#x1f4af;GPTs指令 中文翻译&#xff1a; 指令保护和安全规则&…...

概率论公式整理

1 概率 古典概型和几何概型 古典概型&#xff08;有限等可能&#xff09;几何概型&#xff08;无限等可能&#xff09; 条件概率 P ( A ∣ B ) P ( A B ) P ( B ) P(A|B) \frac{P(AB)}{P(B)} P(A∣B)P(B)P(AB)​ 全概率公式 P ( B ) ∑ i 1 n P ( A i ) P ( B ∣ A i ) P…...

【C++】—— stack和queue的模拟实现

前言 ​ stack 和 queue使用起来都非常简单&#xff0c;现在来模拟实现一下&#xff0c;理解其底层的原理。 ​ 在实现之前&#xff0c;应该知道&#xff0c;stack 和 queue 都是容器适配器&#xff0c;通过看官网文件也可以看出来&#xff1b;其默认的容器都是deque&#xff…...

管家婆工贸ERP BR039.采购订单关联MRP明细表

最低适用版本&#xff1a; 工贸系列 23.8 插件简要功能说明&#xff1a; 采购订单明细表&#xff0c;支持显示采购订单明细上游请购单明细关联的MRP中对应销售订单明细产成品相关信息更多细节描述见下方详细文档 插件操作视频&#xff1a; 进销存类定制插件--采购订单关联M…...

SwanLab安装教程

SwanLab是一款开源、轻量级的AI实验跟踪工具&#xff0c;提供了一个跟踪、比较、和协作实验的平台&#xff0c;旨在加速AI研发团队100倍的研发效率。 其提供了友好的API和漂亮的界面&#xff0c;结合了超参数跟踪、指标记录、在线协作、实验链接分享、实时消息通知等功能&…...

MySQL EXPLAIN,数据库调优的秘密通道

EXPLAIN 是 MySQL 中一个非常有用的工具&#xff0c;它用于分析 SQL 查询的执行计划。通过 EXPLAIN&#xff0c;你可以获取 MySQL 是如何准备执行你的 SQL 语句的&#xff0c;包括使用的索引、连接类型、扫描的行数等信息。这些信息对于优化查询性能、识别性能瓶颈至关重要。 使…...

利用redis的key失效监听器KeyExpirationEventMessageListener作任务定时提醒功能

某需求&#xff1a; 要求在任务截止日期的前3天时&#xff0c;系统自动给用户发一条消息提醒。 用定时任务的话感觉很不舒服。间隔时间不好弄。不能精准卡到那个点。 由于系统简单&#xff0c;没有使用消息列队&#xff0c;也不能使用延时队列来做。 用Timer的话开销还挺大的&a…...

如何基于Tesseract实现图片的文本识别

在前一篇文章基础上&#xff0c;如何将报告图片中的文本解析出来&#xff0c;最近研究了基于Tesseract的OCR方案&#xff0c;Tesseract OCR是一个开源的OCR引擎&#xff0c;主要结合开源的tesseract和pytesseract&#xff0c;实现了jpg/png等格式图片文本识别&#xff0c;供大家…...

JavaWeb之AJAX

前言 这一节讲JavaWeb之AJAX 1.概述 以前我们在servlet中得到数据&#xff0c;必须通过域给jsp&#xff0c;然后jsp在响应给浏览器 纯html不能获取servlet返回数据 所以我们用jsp 但是现在我们可以同AJAX给返回数据了 我们可以在sevlet中直接通过AJAX返回给浏览器 html中的J…...

算法---解决“汉诺塔”问题

# 初始化步骤计数器 i 1 # 定义移动盘子的函数 def move(n, mfrom, mto): global i # 使用全局变量i来跟踪步骤 print("第%d步:将%d号盘子从%s->%s" % (i, n, mfrom, mto)) # 打印移动步骤 i 1 # 步骤计数器加1 #第一种方法 # 定义汉诺塔问题的递归…...

1-Equity-Transformer:求解NP-Hard Min-Max路由问题的顺序生成算法(AAAI-24)(完)(code)

文章目录 AbstractIntroduction问题表述Methodology多智能体位置编码公平上下文编码训练方案ExperimentsmTSP的性能评估mPDP的性能评估Related WorkConclusionAbstract 最小最大路由问题旨在通过智能体合作完成任务来最小化多个智能体中最长行程的长度。这些问题包括对现实世界…...

linux001.在Oracle VM VirtualBox中ubuntu虚拟系统扩容

1.打开终端切换到virtualBox安装目录 2.输入命令扩容 如上终端中的代码解释&#xff1a; D:\Program Files\Oracle\VirtualBox>.\VBoxManage modifyhd D:\ubuntu18.04\Ubuntu18.04\Ubuntu18.04.vdi --resize 40960如上代码说明&#xff1a;D:\Program Files\Oracle\Virtual…...

RabbitMQ教程:路由(Routing)(四)

文章目录 RabbitMQ教程&#xff1a;路由&#xff08;Routing&#xff09;&#xff08;四&#xff09;一、引言二、基本概念2.1 路由与绑定2.2 Direct交换机2.3 多绑定2.4 发送日志2.5 订阅 三、整合代码3.1 EmitLogDirectApp.cs3.2 ReceiveLogsDirectApp.cs3.3 推送所有和接收e…...

华为Ensp模拟器配置RIP路由协议

目录 RIP路由详解&#xff1a;另一种视角解读 1. RIP简介&#xff1a;轻松理解基础概念 2. RIP的核心机制&#xff1a;距离向量的魅力 3. RIP的实用与局限 RIP配置实验 实验图 ​编辑 PC的ip配置 RIP配置步骤 测试 结语&#xff1a;RIP的今天与明天 RIP路由详解&…...

3. langgraph中的react agent使用 (在react agent添加系统提示)

环境准备 确保你已经安装了以下库&#xff1a; langchainlangchain_openailanggraph 你可以使用以下命令进行安装&#xff1a; pip install langchain langchain_openai langgraph代码实现 1. 初始化模型 首先&#xff0c;我们需要初始化智谱AI的聊天模型。 from langch…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...