当前位置: 首页 > 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…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

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

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

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...