Permutations | & II

Given a collection of distinct numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:

[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

分析:

当array里没有重复数的时候,要找出所有的排列,我们可以把每个数放在第一位,然后获得后面的数排列。利用递归原理,为了获得后面的数的排列,把剩余的数都逐个放在第二位,,,,直到一个新的数组填满。

 1 public class Solution {
 2     public List<List<Integer>> permute(int[] nums) {
 3         List<List<Integer>> list = new ArrayList<List<Integer>>();
 4         permutation(nums, 0, nums.length, list);
 5         return list;
 6     }
 7 
 8     void permutation(int[] arr, int index, int size, List<List<Integer>> list) {
 9         if (index == size) { //填满了
10             addToList(arr, list);
11             return;
12         } 
13         for (int i = index; i < size; i++) {
14             swap(arr, i, index); // 把每个数都放在当前数组的“第一位”
15             permutation(arr, index + 1, size, list); //获得后面的数的排列
16             swap(arr, i, index);
17         }
18     }
19     
20     void addToList(int[] arr, List<List<Integer>> list) {
21         ArrayList<Integer> temp = new ArrayList<Integer>();
22         for (int i : arr) {
23             temp.add(i);
24         }
25         list.add(temp);
26     }
27     
28     void swap(int[] arr, int idx1, int idx2) {
29         int temp = arr[idx1];
30         arr[idx1] = arr[idx2];
31         arr[idx2] = temp;
32     }
33 }

Permutations II

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],
  [2,1,1]
]

分析:

在这个问题里,因为有了重复数字的出现,所以,当把每个数字放在当前数组的第一位的时候,我们需要确保没有重复,我们可以用hashset来check是否重复。

 1 public class Solution {
 2     public List<List<Integer>> permuteUnique(int[] nums) {
 3         List<List<Integer>> list = new ArrayList<List<Integer>>();
 4         Arrays.sort(nums);
 5         permutation(nums, 0, nums.length, list);
 6         return list;
 7     }
 8 
 9     void permutation(int[] arr, int index, int size, List<List<Integer>> list) {
10         if (index == size) {
11             addToList(arr, list);
12             return;
13         } 
15         // when swaping arr[i] with arr[index], we need to make sure the uniqueness of arr[i],
16         // otherwise, we will have duplicates.
17         HashSet<Integer> set = new HashSet<Integer>();
18         for (int i = index; i < size; i++) {
19             if (!set.contains(arr[i])) {
20                 set.add(arr[i]);
21                 swap(arr, i, index);
22                 permutation(arr, index + 1, size, list);
23                 swap(arr, i, index);
24             }
25         }
26     }
27     
28     void swap(int[] arr, int idx1, int idx2) {
29         int temp = arr[idx1];
30         arr[idx1] = arr[idx2];
31         arr[idx2] = temp;
32     }
33 
34     void addToList(int[] arr, List<List<Integer>> list) {
35         ArrayList<Integer> temp = new ArrayList<Integer>();
36         for (int i : arr) {
37             temp.add(i);
38         }
39         list.add(temp);
40     }
41 }

Note: 当时还考虑到用下面的方法来去重复,但是总是通不过,后来才发现,当swap operation完毕以后,后面部分数组已经不是单调递增的了。但是很欣慰的是,自己还是把问题解决了,而且个人认为,上面所讲的方法应该是最容易理解也是最简单的方法。

 1     void permutation(int[] arr, int index, int size, List<List<Integer>> list) {
 2         if (index == size) {
 3             addToList(arr, list);
 4         } else {
 5             for (int i = index; i < size; i++) {
 6                 // arr[i] == arr[index] 不能做,是因为如果和index交换以后,arr[i]有和arr[index]相等,最后一定会重复。
 7                 // arr[i - 1] == arr[i] 也不能做,是因为前面那个值arr[i-1]已经与index交换过了,如果arr[index]和arr[i]再次交换,最后也会重复。
 8                 if (i != index && (arr[i] == arr[index] || arr[i - 1] == arr[i]))
 9                     continue;
10                 swap(arr, i, index);
11                 permutation(arr, index + 1, size, list);
12                 swap(arr, i, index);
13             }
14         }
15     }

参考请注明出处:cnblogs.com/beiyeqingteng

 

转载于:https://www.cnblogs.com/beiyeqingteng/p/5639334.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值