47. 全排列 II

首先介绍一下全排列算法
假设有一数列1,2,3,4
那么1,2,3,4的全排列
perm({1,2,3,4})=1perm({2,3,4})+2perm({1,3,4})+3perm({1,2,4})+4perm(1,2,3)
那么我们只要将每个数,与第一个数交换不就可以得到下一个序列了吗?
比如{1,2,3,4}第一个与第二个数交换,那么不就得到2 {1,3,4}了,接下来我们用一个实际的例子说明该程序是怎样运行的

具体算法流程:

数列:{1,2,3} 第一个与第一个交换
可以得到1 {2,3} 将序列{2,3}放进perm函数递归,然后

——递归{2,3}
数列{2,3}第一个与第一个交换
得到2{3} ,输出1,2,3 (此时low=high,因为序列{3}只有一位数,因此输出列表list)
数列{2,3}第一个与第一个交换回来,结果仍然是{2,3}
数列{2,3}第一个与第二个交换
得到3{2},输出1,3,2
{3,2}又第一个与第二个交换回来,变回{2,3}
—–{2,3}递归完毕序列恢复原状{1,2,3}

数列:{1,2,3} 第一个与第二个交换
可以得到2,{1,3}
——递归{1,3}
数列{1,3}第一个与第一个交换
得到1{3} ,输出2,1,3
数列{1,3}第一个与第一个交换回来,结果仍然是{1,3}
数列{1,3}第一个与第二个交换
得到3{1},输出2,3,1
{3,1}又第一个与第二个交换回来,变回{1,3}
—–{1,3}递归完毕
序列{2,1,3}第一个与第二个交换
序列恢复原状{1,2,3}

数列:{1,2,3} 第一个与第三个交换
可以得到3,{1,2}
——递归{1,2}
数列{1,2}第一个与第一个交换
得到1{2} ,输出3,1,2
数列{1,2}第一个与第一个交换回来,结果仍然是{1,2}
数列{1,2}第一个与第二个交换
得到2{1},输出3,2,1
{2,1}又第一个与第二个交换回来,变回{1,2}
—–{1,2}递归完毕
序列{3,1,2}第一个与第二个交换
序列恢复原状{1,2,3}

算法可以简单地写作
perm({1,2,3})=1perm({2,3})+2perm({1,3})+3perm({1,2})
perm({2,3})=2perm({3})+3perm({2})
perm({1,3})=1perm({3})+3perm({1})
perm({1,2})=1perm({2})+2perm({1})

void perm(vector<int>& nums, int low, int high)
	{
		if (low == high)当low==high时,此时nums就是其中一个排列,输出nums
		{
			for (int i = 0; i <= low; ++i)
				cout << nums[i];
			cout << endl;
		}
		else
		{
			for (int i = low; i <= high; ++i)//每个元素与第一个元素交换
			{
				swap(nums[i], nums[low]);
				perm(nums, low + 1, high);//交换后,得到子序列,用函数perm得到子序列的全排列
				swap(nums[i], nums[low]);//最后,将元素交换回来,复原,然后交换另一个元素
			}
		}
	}

题目:
给定一个可包含重复数字的序列,返回所有不重复的全排列。

示例:

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

思路:
就是在上面全排列算法上多了一步去重
有待改进…

class Solution {
private:
	vector<vector<int>> res;
	bool Count(vector<vector<int>>&nums, vector<int>&t)
	{
		for (int i = 0; i < nums.size(); ++i)
		{
			if (nums[i] == t)
				return false;
		}
		return true;
	}
public:
	void perm(vector<int>& nums, int low, int high)
	{
		if (low == high)
		{
			if(Count(res,nums))
				res.push_back(nums);
		}
		else
		{
			for (int i = low; i <= high; ++i)
			{
				swap(nums[i], nums[low]);
				perm(nums, low + 1, high);
				swap(nums[low], nums[i]);
			}
		}
	}

	vector<vector<int>> permuteUnique(vector<int>& nums) 
	{
		if (nums .size()==0)
			return{ {} };
		if (nums.size() == 1)
			return{ {nums[0]} };

		sort(nums.begin(), nums.end());
		perm(nums, 0, nums.size() - 1);
		return res;
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值