全排列去重

Posted linukey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全排列去重相关的知识,希望对你有一定的参考价值。

全排列去重的前提要求是目标集合必须是经过排序的。

在目标集合排序的前提下,第i位变换数字前后,如果是相同的数字,就会产生重复的排列。

注意:第i位变换的意思是i位本身的变换,而不是i与i-1的比较。

 

[题目链接](https://leetcode.cn/problems/permutations-ii)

代码如下:

void dfs(const vector<int>& nums, int pos, vector<vector<int>>& result, vector<int>& cur) 
    if (pos == nums.size()) 
        result.push_back(cur);
        return;
    

    for (int i = 0; i < nums.size(); ++i) 
        // 控制i位 and 全排列去重
        if (Visited[i] || (i > 0 && nums[i] == nums[i - 1] && !Visited[i - 1])) 
            continue;
        
        Visited[i] = true;
        cur.push_back(nums[i]);
        dfs(nums, pos + 1, result, cur);
        cur.pop_back();
        Visited[i] = false;
    


vector<vector<int>> permuteUnique(vector<int>& nums) 
    vector<vector<int>> result;
    vector<int> cur;
    // 全排列去重的关键是排序过的集合
    sort(nums.begin(), nums.end());
    dfs(nums, 0, result, cur);
    return result;

java 全排列,去重全排列,全组合

import java.util.ArrayList;
import java.util.List;

public class Test {
	
	ArrayList<List<Integer>> list = new ArrayList<List<Integer>> ();
	
    public List<List<Integer>> permute(int[] nums) {
    		solve(nums, 0, nums.length-1);
    		System.out.println(list.toString());
        return list;
    }
    
    
    /** 
     * 算法思想
     * 让每一个元素做首个元素,剩下的start+1递归全排列,之后再换回来,恢复初始状态,让下一个元素做首个元素
     * @param nums
     * @param start
     * @param end
     */
    public void solve(int[] nums, int start, int end) {
    		
    		if (start == end) {
    			list.add(convert(nums));
    		}
    	
    		// 每个元素都尝试和第一个元素互换,剩下的再递归
    		for (int i=start; i<=end; i++) {
    			// 判断第i个元素是否需要和start互换。从start开始判断到i前一个位置是否有和nums[i]相同的元素,如果有表示该元素做过第一个元素,不需要再进行排列
    			if (isSwap(nums, start, i)) {
    				swap(nums, i, start);		// 
        			solve(nums, start+1, end);
        			swap(nums, start, i);		// 处理完再换回来
    			}
    		}
    }
    
    public boolean isSwap(int[] num, int m, int n) {
    		for (int j=m;j<n;j++) {
    			if (num[j] == num[n]) {
    				return false;
    			}
    		}
    		return true;
    }
    
    public void swap(int[] nums, int x, int y) {
    		if (x == y) return;
		System.out.println("交换" + x + ":" + y);
    		int temp = nums[x];
    		nums[x] = nums[y];
    		nums[y] = temp;
    }

    public List<Integer> convert(int[] nums) {
    		ArrayList<Integer> listTemp = new ArrayList<Integer>();
    		for(int i=0;i<nums.length;i++) {
    			listTemp.add(nums[i]);
    		}
    		return listTemp;
    }
	
    public static void main(String[] args) {
		int[] aa = new int[]{1, 2, 3 };
		
		Test n = new Test();
		//n.permute(aa);
		Character[] ch = new Character[]{'a', 'b', 'c'};
		n.solve2(ch);
    }
	
    // 全组合 如a,b,c=>a,b,c,ab,ac,bc,abc
    
    /**
     * 共有2^n-1个结果。对应于位图 001
     * @param arr
     * @return
     */
    public String[] solve2(Character[] arr) {
    		int length = arr.length;
    		int n = 1<<length;
    		for (int i=1;i<n;i++) {
    			for (int j=0;j<length;j++) {
    				if ((i & (1<<j)) > 0) {
    					System.out.print(""+arr[j]);    					
    				}
    	    			
    			}
    			System.out.println();
    		}
    		return null;
    	
    }
}

以上是关于全排列去重的主要内容,如果未能解决你的问题,请参考以下文章

java 字符串全排列 和 去重

[Mdfs] lc剑指 Offer 38. 字符串的排列(全排列+枚举顺序+组合类型枚举+知识理解+模板题)

LeetCode-回溯全排列 II

全排列

Leetcode篇:全排列II

47. 全排列 II