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

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

Tauri2学习笔记

教程地址&#xff1a;https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引&#xff1a;https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多&#xff0c;我按照Tauri1的教程来学习&…...

SQL进阶之旅 Day 22:批处理与游标优化

【SQL进阶之旅 Day 22】批处理与游标优化 文章简述&#xff08;300字左右&#xff09; 在数据库开发中&#xff0c;面对大量数据的处理任务时&#xff0c;单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”&#xff0c;深入探讨如何通过批量操作和游标技术提…...

el-amap-bezier-curve运用及线弧度设置

文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 ‌el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。‌ 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...