一个数n的全排列&&DFS

本文介绍了一个使用深度优先搜索(DFS)实现的全排列算法。该算法能够生成指定长度的所有可能排列组合,并通过递归的方式实现。文章中的代码示例展示了如何初始化变量、避免重复访问以及输出最终结果。
#include<iostream>
#include<string.h>
using namespace std;
int a[10];
bool visit[10];
void dfs(int cur,int n)
{
	if(cur==n+1) return;
	//for(int i=n;i>0;--i)从大到小全排列
	  for(int i=1;i<=n;++i)//从小到大全排列
	 {
		if(!visit[i])
		{
			a[cur]=i;
			visit[i]=true;
			if(cur==n)
			{
				for(int i=1;i<=cur;++i)
				 cout<<a[i];
			     cout<<endl;
			}
			dfs(cur+1,n);
			visit[i]=false;
		}
	}
}
int main()
{
	 int n;
	 while(cin>>n)
	 {
		 memset(visit,false,sizeof(visit));
		 dfs(1,n);
	 }return 0;
}

实现 N 个全排列的算法有多种,下面介绍两种常见的实现方法。 ### 递归回溯法(Java 实现) 递归回溯法是一种通过递归和回溯思想生成全排列的方法。下面是使用 Java 实现的代码: ```java import java.util.ArrayList; import java.util.List; public class Permutations { public static void main(String[] args) { int[] nums = {1, 2, 3}; List<List<Integer>> permutations = generatePermutations(nums); System.out.println(permutations); } public static List<List<Integer>> generatePermutations(int[] nums) { List<List<Integer>> result = new ArrayList<>(); backtrack(result, new ArrayList<>(), nums); return result; } private static void backtrack(List<List<Integer>> result, List<Integer> tempList, int[] nums) { if (tempList.size() == nums.length) { result.add(new ArrayList<>(tempList)); } else { for (int i = 0; i < nums.length; i++) { if (tempList.contains(nums[i])) { continue; // 跳过已经包含的字 } tempList.add(nums[i]); backtrack(result, tempList, nums); tempList.remove(tempList.size() - 1); } } } } ``` 在上述代码中,`generatePermutations` 方法用于生成全排列,`backtrack` 方法是核心的递归回溯函,通过不断尝试将未使用的字加入临时列表,直到临时列表的长度等于组的长度,此时就得到了一个全排列。 ### 递归法(C++ 实现) 同样使用递归思想,下面是 C++ 实现的代码: ```cpp #include<iostream> using namespace std; // a[]组用来存放输入的字 // b[]组用来存放每一个全排列的结果,会一直变化 // vis[]组用来存放a[]组中每个值是否使用过 // countt用来记录n个的时候,全排列的个 int a[1010],b[1010],vis[1010],n,countt=0; void print(){ int i; // 打印其中一个全排列,由n个字构成 for(i=1;i<=n;i++){ cout<<b[i]<<" "; } cout<<endl; // 每打印完一个全排列,计器加一 countt++; } // 这个递归用来求前x个全排列 void dfs(int x){ int i; if(x<=n){ for(i=1;i<=n;i++){ // 如果这个字没有用过,即vis[i]=0,则可以用 if(!vis[i]){ // 将a[i]的值存入b[i] b[x]=a[i]; // 将vis[i]的值设为1,表示不能再用了 vis[i]=1; // 递归求前x+1个字的全排列 dfs(x+1); // 回退一步 vis[i]=0; } } } // 当x=n+1的时候,表示一个全排列已经齐了,可以进行打印了 else{ // 调用print打印函 print(); } } int main(){ int i,j,k; cin>>n; for(i=1;i<=n;i++){ cin>>a[i]; } dfs(1); // 最后打印全排列的种类量,为n! cout<<countt<<endl; } ``` 在这段 C++ 代码中,`dfs` 函是核心的递归函,通过递归和回溯的方式生成全排列,`print` 函用于打印每一个全排列,`vis` 组用于标记字是否已经使用过。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值