排列问题方法总结(递归+迭代)
递归
一、逐步生成结果法(无序)
#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 个位置上的情况。
然后对于每一个其他元素,遍历当前的这个二维数组。然后对于每一个一维数组来说,我的第二个元素他能放在第一个位置是哪个?然后我将它放在这个位置上,然后依次类推第三个元素,它能放的第一个位置就是没有元素占领的位置,然后再把这个新的元素给它保存下来,最终就得到我们的结果。
这个方法其实也不是一个有序的,我们最后也要对它进行排序,然后这个方法其实是利用到排列的每个元素都有可能在每个位置上这样一种思想。
相关文章:
排列问题方法总结(递归+迭代)
递归 一、逐步生成结果法(无序) #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个组件,一个叫CLR(通用语言运行时),另一个是用来构建程序的类库 CLR 用C写一个程序,在一台8688的机器…...
视频质量评价学习笔记
目录 MD VQA:大淘宝团队: ReIQA KVQ 视频质量评价学习笔记 MD VQA:大淘宝团队: 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 是计算机视觉和深度学习领域常见的几个名词,它们分别代表不同的工具、算法和数据集,之间有一些联系和区别。下面分别说明它们的定义、用途以及相互关系。 1. OpenCV(Open Source Computer Vision Library…...
Pandas进行周期与时间戳转换
时间序列数据在数据分析和金融领域非常常见,处理这些数据时,通常会面临周期(Period)与时间戳(Timestamp)之间的转换需求。理解和掌握这种转换,对于时间序列数据的清洗、预处理以及进一步分析至关重要。Python 中的 pandas 库提供了一系列便捷的函数来帮助处理这些时间序…...
【GPTs】Get Simpsonized:一键变身趣味辛普森角色
博客主页: [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 💯GPTs指令💯前言💯Get Simpsonized主要功能适用场景优点缺点使用方式 💯小结 💯GPTs指令 中文翻译: 指令保护和安全规则&…...
概率论公式整理
1 概率 古典概型和几何概型 古典概型(有限等可能)几何概型(无限等可能) 条件概率 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使用起来都非常简单,现在来模拟实现一下,理解其底层的原理。 在实现之前,应该知道,stack 和 queue 都是容器适配器,通过看官网文件也可以看出来;其默认的容器都是dequeÿ…...
管家婆工贸ERP BR039.采购订单关联MRP明细表
最低适用版本: 工贸系列 23.8 插件简要功能说明: 采购订单明细表,支持显示采购订单明细上游请购单明细关联的MRP中对应销售订单明细产成品相关信息更多细节描述见下方详细文档 插件操作视频: 进销存类定制插件--采购订单关联M…...
SwanLab安装教程
SwanLab是一款开源、轻量级的AI实验跟踪工具,提供了一个跟踪、比较、和协作实验的平台,旨在加速AI研发团队100倍的研发效率。 其提供了友好的API和漂亮的界面,结合了超参数跟踪、指标记录、在线协作、实验链接分享、实时消息通知等功能&…...
MySQL EXPLAIN,数据库调优的秘密通道
EXPLAIN 是 MySQL 中一个非常有用的工具,它用于分析 SQL 查询的执行计划。通过 EXPLAIN,你可以获取 MySQL 是如何准备执行你的 SQL 语句的,包括使用的索引、连接类型、扫描的行数等信息。这些信息对于优化查询性能、识别性能瓶颈至关重要。 使…...
利用redis的key失效监听器KeyExpirationEventMessageListener作任务定时提醒功能
某需求: 要求在任务截止日期的前3天时,系统自动给用户发一条消息提醒。 用定时任务的话感觉很不舒服。间隔时间不好弄。不能精准卡到那个点。 由于系统简单,没有使用消息列队,也不能使用延时队列来做。 用Timer的话开销还挺大的&a…...
如何基于Tesseract实现图片的文本识别
在前一篇文章基础上,如何将报告图片中的文本解析出来,最近研究了基于Tesseract的OCR方案,Tesseract OCR是一个开源的OCR引擎,主要结合开源的tesseract和pytesseract,实现了jpg/png等格式图片文本识别,供大家…...
JavaWeb之AJAX
前言 这一节讲JavaWeb之AJAX 1.概述 以前我们在servlet中得到数据,必须通过域给jsp,然后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.输入命令扩容 如上终端中的代码解释: D:\Program Files\Oracle\VirtualBox>.\VBoxManage modifyhd D:\ubuntu18.04\Ubuntu18.04\Ubuntu18.04.vdi --resize 40960如上代码说明:D:\Program Files\Oracle\Virtual…...
RabbitMQ教程:路由(Routing)(四)
文章目录 RabbitMQ教程:路由(Routing)(四)一、引言二、基本概念2.1 路由与绑定2.2 Direct交换机2.3 多绑定2.4 发送日志2.5 订阅 三、整合代码3.1 EmitLogDirectApp.cs3.2 ReceiveLogsDirectApp.cs3.3 推送所有和接收e…...
华为Ensp模拟器配置RIP路由协议
目录 RIP路由详解:另一种视角解读 1. RIP简介:轻松理解基础概念 2. RIP的核心机制:距离向量的魅力 3. RIP的实用与局限 RIP配置实验 实验图 编辑 PC的ip配置 RIP配置步骤 测试 结语:RIP的今天与明天 RIP路由详解&…...
3. langgraph中的react agent使用 (在react agent添加系统提示)
环境准备 确保你已经安装了以下库: langchainlangchain_openailanggraph 你可以使用以下命令进行安装: pip install langchain langchain_openai langgraph代码实现 1. 初始化模型 首先,我们需要初始化智谱AI的聊天模型。 from langch…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
