leetcode--Permutations II

本文介绍了一种算法,用于从可能包含重复元素的整数集合中返回所有可能的独特排列。通过一系列交换操作,避免了重复结果的产生,确保了最终输出的唯一性。该算法实现了O(n^2)次交换,有效地解决了重复排列的问题。

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

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[1,1,2][1,2,1], and [2,1,1].

 

public class Solution {
    /**
	 * To obtain a new permutation, given a permutation, we need to implement a series of swaps between 
	 * two indices. All swaps are represented by indices as the following form (i, j), where i <= j.<br>
	 * So, in order to get all permutations, we only need to implements O(n^2) swaps. 
	 * @param num -int array
	 * @return List<List<Integer> > -all permutations
	 * @author Averill Zheng
	 * @version 2014-06-24
	 * @since JDK 1.7
	 */
    public List<List<Integer>> permuteUnique(int[] num) {
        List<List<Integer> > result = new ArrayList<List<Integer> >();
		int length = num.length;
		if(length > 0){
			List<Integer> startPermutation = new ArrayList<Integer>();
			for(int s : num)
				startPermutation.add(s);
			result.add(startPermutation);
			
			//classify all swaps into groups(1, j), (2, j), ...(length - 2, j)
			for(int i = 0; i < length - 1; ++i){
				List<List<Integer> > tempResult = new ArrayList<List<Integer> >();
				while(!result.isEmpty()){
					List<Integer> oldPermutation = result.remove(0);
					//use a HashSet to record the duplications.
					Set<Integer> alreadySwapped = new HashSet<Integer>();
					//j starts from i, NOT i + 1, because we need to save original permutation back to tempResult
					for(int j = i; j < length; ++j) {
						if(!alreadySwapped.contains(oldPermutation.get(j))) {
							List<Integer> newListBySwapping = new ArrayList<Integer>();
							newListBySwapping.addAll(oldPermutation);
							//swap oldPermutation.get(i) and oldPermutation.get(j)
							int valueAtJ = oldPermutation.get(j);
							newListBySwapping.set(j, oldPermutation.get(i));
							newListBySwapping.set(i, valueAtJ);
							alreadySwapped.add(valueAtJ);
							tempResult.add(newListBySwapping);
						}
					}
				}
				result = tempResult;
			}
		}
		return result;
    }
}

  

  

转载于:https://www.cnblogs.com/averillzheng/p/3542227.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值