花样全排列(leetcode46,leetcode47)

普通全排列

普通方法

dfs+bool数组判断是否访问过

花样方法

dfs + 交换头元素
http://xiaohuiliucuriosity.blogspot.com/2014/12/permutations.html
permutation of A[1…n] equals to
A[1] + permutation of (A[1…n] - A[1])
A[2] + permutation of (A[1…n] - A[2])

A[n] + permutation of (A[1…n] - A[n]).
通过交换的方法来修改第一个数值
swap(num[begin], num[i]);

去重全排列

有重复元素,全排列的结果不能重复

我的思路

很简单的思路。在全排列的基础上,对每一层进行判断,该层相同的元素只能被往下递归一次。
编程采用了map判断该元素是否重复出现

正常人的思路

类似于数学上的C排列和A排列,强行为重复的元素设定取值的优先顺序。
排序后,只有排在前面的值用了,排在后面的值才能用。
以1 1 2 为例
第一个结果 1 1 2
第二个结果 1 2 1
第三个结果 2 1 1(不能是1 1 2因为第二个1不能排在第一个1前面。也不会有第四个结果)
核心代码:排序+ //下一个重复值只有在前一个重复值被使用的情况下才可以使用
if(i>0 &&nums[i-1]==nums[i] && !used[i-1]) continue;

大佬的思路

保证每次取出的头元素都是不重复的。
注意递归时使用的是vector< int > num,不带&也就是每次回到当前层,num值都是上一层的值,即后面递归的操作不对当前层产生影响
并且顺序变化后不变回来

核心代码:排序+ if(i != begin &&num[begin] == num[i])continue;
eg:
1 1 2 2 3
2 1 1 2 3(头元素已经变成2了,头元素只2一次)
3 1 1 2 1

代码

去重全排列之我的代码

class Solution {
public:
    vector<vector<int>> ans;
    vector<int>index;
    vector<map<int,int>>exists;
    map<int,int>mapp;
    void dfs(int deep,vector<int>&per, vector<int> &nums)
    {
        int n = nums.size();
        if (deep == n)
        {
            ans.push_back(per);
            return;
        }
        for(int i = 0; i < n; i ++)
        {   
            if(!index[i] &&!exists[deep][nums[i]]){
            exists[deep][nums[i]] ++;
            index[i] = 1;
            per.push_back(nums[i]);
            dfs(deep + 1,per,nums);
            per.pop_back();
         //   exists[deep][nums[i]]--;
            index[i] = 0;
            }
        }
        exists[deep].clear();
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<int> per;
        mapp.clear();
        int n = nums.size();
        for(int i = 0; i < n; i ++)
        {
            index.push_back(0);
            exists.push_back(mapp); 
        }
        dfs(0,per,nums);
        return ans;
    }
};

去重全排列大佬的代码

class Solution {
public:
    vector<vector<int> > permuteUnique(vector<int> &num) {
	    vector<vector<int> > result;
        sort(num.begin(),num.end());
	    
	    permuteRecursive(num, 0, result);
	    return result;
    }
    
    // permute num[begin..end]
    // invariant: num[0..begin-1] have been fixed/permuted
	void permuteRecursive(vector<int> num, int begin, vector<vector<int> > &result)	{
		if (begin == num.size() - 1) {
		    // one permutation instance
		    result.push_back(num);
		    return;
		}
		
		for (int i = begin; i < num.size(); i++) {
            if(i != begin &&num[begin] == num[i])continue;
		    swap(num[begin], num[i]);
		    permuteRecursive(num, begin + 1, result);
		    // reset
		    //swap(num[begin], num[i]);
		}
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值