-
Notifications
You must be signed in to change notification settings - Fork 21
/
47. Permutations II.java
executable file
·162 lines (137 loc) · 4.35 KB
/
47. Permutations II.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
M
tags: Backtracking, DFS
time O(n!)
space: O(n!)
给一串数组, 找出所有permutation数组. 注意: 给出的nums里面有重复数字, 而permutation的结果需要无重复.
Similar to 46. Permutations, but with dedup
#### Backtracking
- Sort the list, and on same level, if last element is the same as curr, skip this recursive call
- time O(n!)
#### Non-recursive, manuall swap
- Idea from: https://www.sigmainfy.com/blog/leetcode-permutations-i-and-ii.html
- 用到 sublist sort
- 用 swap function, 在原数组上调节出来新的permutation
- 注意: 每次拿到新的candidate, 都要把没有permutate的数位sort, 然后再开始swap.
- 这是为了确保, [j]和[j-1]在重复时候, 不用重新记录.
```
/*
Given a collection of numbers that might contain duplicates,
return all possible unique permutations.
Example
For numbers [1,2,2] the unique permutations are:
[
[1,2,2],
[2,1,2],
[2,2,1]
]
Challenge
Do it without recursion.
Tags Expand
LinkedIn Recursion
*/
// option1 with remaining Queue
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
if (nums == null || nums.length == 0) return new ArrayList<>();
Queue<Integer> queue = new LinkedList<>();
Arrays.sort(nums);
for (int num : nums) queue.offer(num); // [1, 2, 3]
List<List<Integer>> rst = new ArrayList<>();
dfs(rst, new ArrayList<>(), queue);
return rst;
}
private void dfs(List<List<Integer>> rst, List list, Queue<Integer> queue) {
if (queue.isEmpty()) { //
rst.add(new ArrayList<>(list));
return;
}
int size = queue.size();
Integer last = null;
while (size-- > 0) {
int val = queue.poll();
if (last != null && last == val) {
queue.offer(val);
continue;
}
list.add(val);
dfs(rst, list, queue);
list.remove(list.size() - 1);
queue.offer(val);
last = val;
}
}
}
// option2: Use visited[i] to mark visited copies, then skip [i-1] item
class Solution {
boolean[] visited;
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> rst = new ArrayList<>();
if (nums == null || nums.length == 0) {
return rst;
}
Arrays.sort(nums);
int n = nums.length;
visited = new boolean[n];
dfs(rst, new ArrayList<>(), nums);
return rst;
}
private void dfs(List<List<Integer>> rst, List<Integer> list, int[] nums) {
if (list.size() == nums.length) {
rst.add(new ArrayList<>(list));
return;
}
for (int i = 0; i < nums.length; i++) {
if (visited[i] || (i - 1 >= 0 && visited[i - 1] && nums[i] == nums[i - 1])) {
continue;
}
visited[i] = true;
list.add(nums[i]);
dfs(rst, list, nums);
visited[i] = false;
list.remove(list.size() - 1);
}
}
}
// Sort
/*
Thoughts:
1. Use nums to swap nodes
2. Each swap should produce a unique row
3. Iterate over position to swap x, and then iterative over (x + 1, n) to swap each one
*/
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> rst = new ArrayList<>();
if (nums == null || nums.length == 0) {
return rst;
}
int n = nums.length;
Arrays.sort(nums);
List<Integer> list = new ArrayList<>();
for (int num : nums) {
list.add(num);
}
rst.add(new ArrayList<>(list));
for (int pos = 0; pos < n; pos++) {
for (int i = rst.size() - 1; i >= 0; i--) {
list = rst.get(i);
Collections.sort(list.subList(pos, list.size()));
for (int j = pos + 1; j < n; j++) {
if (list.get(j) == list.get(j - 1)) {
continue;
}
swap(list, pos, j);
rst.add(new ArrayList<>(list));
swap(list, pos, j);
}
}
}
return rst;
}
private void swap(List<Integer> list, int x, int y) {
int temp = list.get(x);
list.set(x, list.get(y));
list.set(y, temp);
}
}
```