全排列 2

97 篇文章 7 订阅
58 篇文章 3 订阅

题目描述来源:力扣(LeetCode))
给定一个可包含重复数字的序列,返回所有不重复的全排列。(输入的数范围为 1~n)

示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]


思路分析
大体框架是回溯或者DFS,其次针对该问题核心是如何避免重复的排列出现。
采取的可行的措施就是在每个数每次进入排列的某个位置的时候,我们可以设置一个标志,如使用last存第一次给该位置赋的值,在第二次给同样的位置赋值的时候应该与上一次该位置的赋值进行比较,若相等,就不能再放该数在目前位置上,如图:
在这里插入图片描述
第一次v = 1的第一层递归:从num [ 1 ] ,即第一个1开始进入排列数组,第一次递归排序无需考虑重复;
在这里插入图片描述
第一次v = 1第二层递归:
在这里插入图片描述

第二次v = 2开始第一层递归:从num [ 2 ],即第二个1开始进入排列数组,发现上一层递归中last == 1,那么num [ 2 ]此时不能进入排列数组,到num [ 3 ],即第一个2进入排列数组,并且更新last,last = 2,再进行递归即可。
在这里插入图片描述
整个过程
在这里插入图片描述


代码实现

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define Maxsize 1000
int n, visited[Maxsize];
int cunt;
int parent[Maxsize];
void  Recall(int *, int, int);//回溯函数
int main()
{
	int num[Maxsize], i;
	cin >> n;//输入项数
	for (i = 1; i <= n; i++)
		cin >> num[i];
	memset(parent,0,sizeof(int)*(n + 1));//初始化 
	memset(visited,0,sizeof(int)*(n + 1));
	sort(num + 1,num + 1 + n);//库函数排序 
	Recall(num, 1, 0);//调用递归函数 
	cout << "一共有" << cunt << "种全排列" << endl;
	return 0;
}
void Recall(int num[], int i, int cnt)
{
	int v, w;
	if (cnt == n)//全部排列进去后,结束该层递归 
	{
		cunt++;//种类累计变量 
		for (w = 1; w <= n; w++)//输出该次排列元素 
		cout << parent[w] << " ";
		cout << endl;
		return;
	}
	int last = 0;
	for (v = 1; v <= n; v++)
	{
		if (visited[v] == 0 && last != num[v])//没有被访问过,
		{
			parent[++cnt] = num[v];//进入排列 
			last = num[v];//改变最后一次该位的赋值 
			visited[v] = 1;//标记已访问 
			Recall(num, v, cnt);//递归下一层 
			visited[v] = 0;//上述递归完成后,回溯 
			cnt--;//消去上层递归已进入元素 
		}
	}
}

运行结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
p1395是指LeetCode上的题目编号为1395的题目,全排列2是指该题目的具体名称。该题目的描述如下: 给定一个整数数组nums,返回满足以下条件的三元组 (i, j, k) 的数量: - 0 <= i < j < k < nums.length - nums[i] < nums[j] < nums[k] 换句话说,要求找出数组中满足递增顺序的三元组的数量。 解决这个问题的一种方法是使用回溯算法来生成所有可能的三元组,并计算满足条件的数量。具体步骤如下: 1. 定义一个计数器count,用于记录满足条件的三元组的数量。 2. 定义一个辅助函数backtrack,该函数接收三个参数:当前遍历到的位置index,当前已选择的元素集合path,以及计数器count。 3. 在backtrack函数中,首先判断当前已选择的元素集合path的长度是否为3,如果是,则判断是否满足递增顺序条件,如果是,则将计数器count加1。 4. 然后,在当前位置index开始遍历数组nums,对于每个位置,如果该位置的元素不在当前已选择的元素集合path中,则将该元素加入path,并递归调用backtrack函数。 5. 最后,在backtrack函数结束后,返回计数器count的值。 以下是使用回溯算法解决该问题的示例代码: ```python class Solution: def numTriplets(self, nums: List[int]) -> int: count = 0 self.backtrack(nums, [], count) return count def backtrack(self, nums, path, count): if len(path) == 3: if path[0] < path[1] < path[2]: count += 1 return for i in range(len(nums)): if nums[i] not in path: path.append(nums[i]) self.backtrack(nums, path, count) path.pop() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值