递归方法求全排列

本文介绍了一个简单的全排列问题解决方法,通过递归的方式实现了给定数字集合的所有可能排列,并提供了完整的C语言代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*****************************************************************\
全排列问题 例如,
输入: 
3
1 2 3
输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
\*****************************************************************/
#include<stdio.h>
#include<string.h>
#include<assert.h>

const int maxn = 100;

int num[maxn];
bool used[maxn];
int ans[maxn];

void output(int n)
{
	for(int i=0; i<n; i++)
	{
		if(i < n-1)
			printf("%d ", ans[i]);
		else
			printf("%d\n", ans[i]);
	}
}

void fullPerm(int n, int dep)
{
	if(dep >= n)
	{
		output(dep);
		return;
	}
	for(int i=0; i<n; i++)
	{
		if(!used[i])
		{
			used[i] = true;
			ans[dep] = num[i];
			fullPerm(n, dep+1);
			used[i] = false;
		}
	}
}

void test()
{
	int n = 0;
	while(scanf("%d", &n) != EOF)
	{
		if(n == 0) break;
		for(int i=0; i<n; i++)
			scanf("%d", &num[i]);
		memset(used, false, sizeof(used));
		memset(ans, -1, sizeof(ans));
		fullPerm(n, 0);
	}
}

int main()
{
	test();
	return 0;
}

### 使用 DFS 实现全排列算法 全排列问题是经典的组合数学问题之一,通常可以通过深度优先搜索 (DFS) 来解决。以下是基于引用中的描述和代码示例构建的一个完整的解决方案。 #### 算法思路 通过递归的方式逐步构造每一个可能的排列。为了防止重复访问同一个元素,在遍历过程中引入一个布尔数组 `on_path` 或者类似的标记机制来记录当前路径上已经使用的元素[^1]。当路径长度等于输入列表的长度时,表示找到了一个新的排列,将其加入结果集中[^2]。 #### Python 示例代码 下面是一个标准的实现方式: ```python class Solution: def permute(self, nums: list[int]) -> list[list[int]]: result = [] # 定义辅助函数用于递归调用 def dfs(path, on_path): if len(path) == len(nums): # 边界条件:如果当前路径已达到最大长度,则保存该路径 result.append(path[:]) return for i in range(len(nums)): # 遍历所有可选节点 if not on_path[i]: # 如果未被访问过则继续处理 on_path[i] = True # 标记为已访问 path.append(nums[i]) # 加入当前路径 dfs(path, on_path) # 进一步探索下一层级 path.pop() # 回溯:移除最后一个元素恢复原始状态 on_path[i] = False # 解锁以便后续其他分支可以再次使用 initial_on_path = [False] * len(nums) dfs([], initial_on_path) return result ``` 此版本解决了之前提到因缺少传递新副本而导致的问题,并且保持了清晰易懂结构化设计。 另外针对含有重复项情况下的去重需求也有相应调整方案给出作为补充说明[^3]: ```python def permuteUnique(self, nums: List[int]) -> List[List[int]]: nums.sort() res = [] def backtrack(path=[], used=[False]*len(nums)): if len(path)==len(nums): res.append(list(path)) return seen=set() for idx,num in enumerate(nums): if used[idx]: continue elif num in seen: continue else: seen.add(num) used[idx]=True path.append(num) backtrack(path,used) path.pop() used[idx]=False backtrack() return res ``` 上述两段程序分别展示了基础版无重复元素情形以及考虑到了可能存在相同数值情况下如何有效去除冗余解集的方法。 最后值得注意的是无论哪种形式都需要遵循一定框架模式即定义好终止条件之后逐一尝试可行选项直至完成整个树形图枚举过程同时记得适时撤销先前所做的更改以允许别的可能性得以展开探讨[^4][^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值