Skip to content

Commit 0919dea

Browse files
committed
feat: add solutions to lc problem: No.0047
No.0047.Permutations II
1 parent 3260ac9 commit 0919dea

File tree

9 files changed

+381
-368
lines changed

9 files changed

+381
-368
lines changed

solution/0000-0099/0046.Permutations/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@
5151

5252
时间复杂度 $O(n\times n!)$,其中 $n$ 是数组的长度。一共有 $n!$ 个排列,每个排列需要 $O(n)$ 的时间来构造。
5353

54+
相似题目:
55+
56+
- [47. 全排列 II](/solution/0000-0099/0047.Permutations%20II/README.md)
57+
5458
<!-- tabs:start -->
5559

5660
### **Python3**

solution/0000-0099/0047.Permutations II/README.md

+141-128
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,22 @@
4040

4141
<!-- 这里可写通用的实现逻辑 -->
4242

43-
排序 + 深度优先搜索。
43+
**方法一:排序 + 回溯**
44+
45+
我们可以先对数组进行排序,这样就可以将重复的数字放在一起,方便我们进行去重。
46+
47+
然后,我们设计一个函数 $dfs(i)$,表示当前需要填写第 $i$ 个位置的数。函数的具体实现如下:
48+
49+
- 如果 $i = n$,说明我们已经填写完毕,将当前排列加入答案数组中,然后返回。
50+
- 否则,我们枚举第 $i$ 个位置的数 $nums[j]$,其中 $j$ 的范围是 $[0, n - 1]$。我们需要保证 $nums[j]$ 没有被使用过,并且与前面枚举的数不同,这样才能保证当前排列不重复。如果满足条件,我们就可以填写 $nums[j]$,并继续递归地填写下一个位置,即调用 $dfs(i + 1)$。在递归调用结束后,我们需要将 $nums[j]$ 标记为未使用,以便于进行后面的枚举。
51+
52+
在主函数中,我们首先对数组进行排序,然后调用 $dfs(0)$,即从第 0 个位置开始填写,最终返回答案数组即可。
53+
54+
时间复杂度 $O(n \times n!)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。需要进行 $n!$ 次枚举,每次枚举需要 $O(n)$ 的时间来判断是否重复。另外,我们需要一个标记数组来标记每个位置是否被使用过,因此空间复杂度为 $O(n)$。
55+
56+
相似题目:
57+
58+
- [46. 全排列](/solution/0000-0099/0046.Permutations/README.md)
4459

4560
<!-- tabs:start -->
4661

@@ -51,26 +66,25 @@
5166
```python
5267
class Solution:
5368
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
54-
n = len(nums)
55-
res = []
56-
path = [0] * n
57-
used = [False] * n
58-
nums.sort()
59-
60-
def dfs(u):
61-
if u == n:
62-
res.append(path.copy())
69+
def dfs(i: int):
70+
if i == n:
71+
ans.append(t[:])
6372
return
64-
for i in range(n):
65-
if used[i] or (i > 0 and nums[i] == nums[i - 1] and not used[i - 1]):
73+
for j in range(n):
74+
if vis[j] or (j and nums[j] == nums[j - 1] and not vis[j - 1]):
6675
continue
67-
path[u] = nums[i]
68-
used[i] = True
69-
dfs(u + 1)
70-
used[i] = False
76+
t[i] = nums[j]
77+
vis[j] = True
78+
dfs(i + 1)
79+
vis[j] = False
7180

81+
n = len(nums)
82+
nums.sort()
83+
ans = []
84+
t = [0] * n
85+
vis = [False] * n
7286
dfs(0)
73-
return res
87+
return ans
7488
```
7589

7690
### **Java**
@@ -79,31 +93,33 @@ class Solution:
7993

8094
```java
8195
class Solution {
96+
private List<List<Integer>> ans = new ArrayList<>();
97+
private List<Integer> t = new ArrayList<>();
98+
private int[] nums;
99+
private boolean[] vis;
100+
82101
public List<List<Integer>> permuteUnique(int[] nums) {
83-
List<List<Integer>> res = new ArrayList<>();
84-
List<Integer> path = new ArrayList<>();
85-
int n = nums.length;
86-
boolean[] used = new boolean[n];
87102
Arrays.sort(nums);
88-
dfs(0, n, nums, used, path, res);
89-
return res;
103+
this.nums = nums;
104+
vis = new boolean[nums.length];
105+
dfs(0);
106+
return ans;
90107
}
91108

92-
private void dfs(
93-
int u, int n, int[] nums, boolean[] used, List<Integer> path, List<List<Integer>> res) {
94-
if (u == n) {
95-
res.add(new ArrayList<>(path));
109+
private void dfs(int i) {
110+
if (i == nums.length) {
111+
ans.add(new ArrayList<>(t));
96112
return;
97113
}
98-
for (int i = 0; i < n; ++i) {
99-
if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) {
114+
for (int j = 0; j < nums.length; ++j) {
115+
if (vis[j] || (j > 0 && nums[j] == nums[j - 1] && !vis[j - 1])) {
100116
continue;
101117
}
102-
path.add(nums[i]);
103-
used[i] = true;
104-
dfs(u + 1, n, nums, used, path, res);
105-
used[i] = false;
106-
path.remove(path.size() - 1);
118+
t.add(nums[j]);
119+
vis[j] = true;
120+
dfs(i + 1);
121+
vis[j] = false;
122+
t.remove(t.size() - 1);
107123
}
108124
}
109125
}
@@ -115,129 +131,126 @@ class Solution {
115131
class Solution {
116132
public:
117133
vector<vector<int>> permuteUnique(vector<int>& nums) {
118-
int n = nums.size();
119-
vector<vector<int>> res;
120-
vector<int> path(n, 0);
121-
vector<bool> used(n, false);
122134
sort(nums.begin(), nums.end());
123-
dfs(0, n, nums, used, path, res);
124-
return res;
125-
}
126-
127-
void dfs(int u, int n, vector<int>& nums, vector<bool>& used, vector<int>& path, vector<vector<int>>& res) {
128-
if (u == n) {
129-
res.emplace_back(path);
130-
return;
131-
}
132-
for (int i = 0; i < n; ++i) {
133-
if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) continue;
134-
path[u] = nums[i];
135-
used[i] = true;
136-
dfs(u + 1, n, nums, used, path, res);
137-
used[i] = false;
138-
}
139-
}
140-
};
141-
```
142-
143-
### **C#**
144-
145-
```cs
146-
using System.Collections.Generic;
147-
using System.Linq;
148-
149-
public class Solution {
150-
public IList<IList<int>> PermuteUnique(int[] nums) {
151-
var results = new List<IList<int>>();
152-
var temp = new List<int>();
153-
var count = nums.GroupBy(n => n).ToDictionary(g => g.Key, g => g.Count());
154-
Search(count, temp, results);
155-
return results;
156-
}
157-
158-
private void Search(Dictionary<int, int> count, IList<int> temp, IList<IList<int>> results)
159-
{
160-
if (!count.Any() && temp.Any())
161-
{
162-
results.Add(new List<int>(temp));
163-
return;
164-
}
165-
var keys = count.Keys.ToList();
166-
foreach (var key in keys)
167-
{
168-
temp.Add(key);
169-
--count[key];
170-
if (count[key] == 0) count.Remove(key);
171-
Search(count, temp, results);
172-
temp.RemoveAt(temp.Count - 1);
173-
if (count.ContainsKey(key))
174-
{
175-
++count[key];
135+
int n = nums.size();
136+
vector<vector<int>> ans;
137+
vector<int> t(n);
138+
vector<bool> vis(n);
139+
function<void(int)> dfs = [&](int i) {
140+
if (i == n) {
141+
ans.emplace_back(t);
142+
return;
176143
}
177-
else
178-
{
179-
count[key] = 1;
144+
for (int j = 0; j < n; ++j) {
145+
if (vis[j] || (j && nums[j] == nums[j - 1] && !vis[j - 1])) {
146+
continue;
147+
}
148+
t[i] = nums[j];
149+
vis[j] = true;
150+
dfs(i + 1);
151+
vis[j] = false;
180152
}
181-
}
153+
};
154+
dfs(0);
155+
return ans;
182156
}
183-
}
157+
};
184158
```
185159
186160
### **Go**
187161
188162
```go
189-
func permuteUnique(nums []int) [][]int {
190-
n := len(nums)
191-
res := make([][]int, 0)
192-
path := make([]int, n)
193-
used := make([]bool, n)
163+
func permuteUnique(nums []int) (ans [][]int) {
194164
sort.Ints(nums)
195-
dfs(0, n, nums, used, path, &res)
196-
return res
197-
}
198-
199-
func dfs(u, n int, nums []int, used []bool, path []int, res *[][]int) {
200-
if u == n {
201-
t := make([]int, n)
202-
copy(t, path)
203-
*res = append(*res, t)
204-
return
205-
}
206-
for i := 0; i < n; i++ {
207-
if used[i] || (i > 0 && nums[i] == nums[i-1] && !used[i-1]) {
208-
continue
165+
n := len(nums)
166+
t := make([]int, n)
167+
vis := make([]bool, n)
168+
var dfs func(int)
169+
dfs = func(i int) {
170+
if i == n {
171+
cp := make([]int, n)
172+
copy(cp, t)
173+
ans = append(ans, cp)
174+
return
175+
}
176+
for j := 0; j < n; j++ {
177+
if vis[j] || (j > 0 && nums[j] == nums[j-1] && !vis[j-1]) {
178+
continue
179+
}
180+
vis[j] = true
181+
t[i] = nums[j]
182+
dfs(i + 1)
183+
vis[j] = false
209184
}
210-
path[u] = nums[i]
211-
used[i] = true
212-
dfs(u+1, n, nums, used, path, res)
213-
used[i] = false
214185
}
186+
dfs(0)
187+
return
215188
}
216189
```
217190

218191
### **TypeScript**
219192

220193
```ts
221194
function permuteUnique(nums: number[]): number[][] {
195+
nums.sort((a, b) => a - b);
222196
const n = nums.length;
223-
const res: number[][] = [];
197+
const ans: number[][] = [];
198+
const t: number[] = new Array(n);
199+
const vis: boolean[] = new Array(n);
224200
const dfs = (i: number) => {
225201
if (i === n) {
226-
res.push([...nums]);
202+
ans.push(t.slice());
203+
return;
227204
}
228-
const set = new Set<number>();
229-
for (let j = i; j < n; j++) {
230-
if (set.has(nums[j])) {
205+
for (let j = 0; j < n; ++j) {
206+
if (vis[j] || (j > 0 && nums[j] === nums[j - 1] && !vis[j - 1])) {
231207
continue;
232208
}
233-
set.add(nums[j]);
234-
[nums[i], nums[j]] = [nums[j], nums[i]];
209+
t[i] = nums[j];
210+
vis[j] = true;
235211
dfs(i + 1);
236-
[nums[i], nums[j]] = [nums[j], nums[i]];
212+
vis[j] = false;
237213
}
238214
};
239215
dfs(0);
240-
return res;
216+
return ans;
217+
}
218+
```
219+
220+
### **C#**
221+
222+
```cs
223+
public class Solution {
224+
private List<IList<int>> ans = new List<IList<int>>();
225+
private List<int> t = new List<int>();
226+
private int[] nums;
227+
private bool[] vis;
228+
229+
public IList<IList<int>> PermuteUnique(int[] nums) {
230+
Array.Sort(nums);
231+
int n = nums.Length;
232+
vis = new bool[n];
233+
this.nums = nums;
234+
dfs(0);
235+
return ans;
236+
}
237+
238+
private void dfs(int i) {
239+
if (i == nums.Length) {
240+
ans.Add(new List<int>(t));
241+
return;
242+
}
243+
for (int j = 0; j < nums.Length; ++j) {
244+
if (vis[j] || (j > 0 && nums[j] == nums[j - 1] && !vis[j - 1])) {
245+
continue;
246+
}
247+
vis[j] = true;
248+
t.Add(nums[j]);
249+
dfs(i + 1);
250+
t.RemoveAt(t.Count - 1);
251+
vis[j] = false;
252+
}
253+
}
241254
}
242255
```
243256

0 commit comments

Comments
 (0)