Skip to content

Commit 59cb267

Browse files
authored
feat: add solutions to lc problem: No.0047 (#4031)
1 parent 0aa2781 commit 59cb267

File tree

7 files changed

+200
-82
lines changed

7 files changed

+200
-82
lines changed

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

+68-27
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ tags:
5858

5959
我们可以先对数组进行排序,这样就可以将重复的数字放在一起,方便我们进行去重。
6060

61-
然后,我们设计一个函数 $dfs(i)$,表示当前需要填写第 $i$ 个位置的数。函数的具体实现如下:
61+
然后,我们设计一个函数 $\textit{dfs}(i)$,表示当前需要填写第 $i$ 个位置的数。函数的具体实现如下:
6262

6363
- 如果 $i = n$,说明我们已经填写完毕,将当前排列加入答案数组中,然后返回。
64-
- 否则,我们枚举第 $i$ 个位置的数 $nums[j]$,其中 $j$ 的范围是 $[0, n - 1]$。我们需要保证 $nums[j]$ 没有被使用过,并且与前面枚举的数不同,这样才能保证当前排列不重复。如果满足条件,我们就可以填写 $nums[j]$,并继续递归地填写下一个位置,即调用 $dfs(i + 1)$。在递归调用结束后,我们需要将 $nums[j]$ 标记为未使用,以便于进行后面的枚举。
64+
- 否则,我们枚举第 $i$ 个位置的数 $nums[j]$,其中 $j$ 的范围是 $[0, n - 1]$。我们需要保证 $nums[j]$ 没有被使用过,并且与前面枚举的数不同,这样才能保证当前排列不重复。如果满足条件,我们就可以填写 $nums[j]$,并继续递归地填写下一个位置,即调用 $\textit{dfs}(i + 1)$。在递归调用结束后,我们需要将 $nums[j]$ 标记为未使用,以便于进行后面的枚举。
6565

66-
在主函数中,我们首先对数组进行排序,然后调用 $dfs(0)$,即从第 0 个位置开始填写,最终返回答案数组即可。
66+
在主函数中,我们首先对数组进行排序,然后调用 $\textit{dfs}(0)$,即从第 0 个位置开始填写,最终返回答案数组即可。
6767

6868
时间复杂度 $O(n \times n!)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。需要进行 $n!$ 次枚举,每次枚举需要 $O(n)$ 的时间来判断是否重复。另外,我们需要一个标记数组来标记每个位置是否被使用过,因此空间复杂度为 $O(n)$。
6969

@@ -141,12 +141,12 @@ class Solution {
141141
class Solution {
142142
public:
143143
vector<vector<int>> permuteUnique(vector<int>& nums) {
144-
sort(nums.begin(), nums.end());
144+
ranges::sort(nums);
145145
int n = nums.size();
146146
vector<vector<int>> ans;
147147
vector<int> t(n);
148148
vector<bool> vis(n);
149-
function<void(int)> dfs = [&](int i) {
149+
auto dfs = [&](this auto&& dfs, int i) {
150150
if (i == n) {
151151
ans.emplace_back(t);
152152
return;
@@ -171,7 +171,7 @@ public:
171171
172172
```go
173173
func permuteUnique(nums []int) (ans [][]int) {
174-
sort.Ints(nums)
174+
slices.Sort(nums)
175175
n := len(nums)
176176
t := make([]int, n)
177177
vis := make([]bool, n)
@@ -203,8 +203,8 @@ function permuteUnique(nums: number[]): number[][] {
203203
nums.sort((a, b) => a - b);
204204
const n = nums.length;
205205
const ans: number[][] = [];
206-
const t: number[] = new Array(n);
207-
const vis: boolean[] = new Array(n);
206+
const t: number[] = Array(n);
207+
const vis: boolean[] = Array(n).fill(false);
208208
const dfs = (i: number) => {
209209
if (i === n) {
210210
ans.push(t.slice());
@@ -228,34 +228,75 @@ function permuteUnique(nums: number[]): number[][] {
228228
#### Rust
229229

230230
```rust
231-
use std::collections::HashSet;
232231
impl Solution {
233-
fn dfs(i: usize, nums: &mut Vec<i32>, res: &mut Vec<Vec<i32>>) {
232+
pub fn permute_unique(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
233+
nums.sort();
234234
let n = nums.len();
235-
if i == n {
236-
res.push(nums.clone());
237-
return;
238-
}
239-
let mut set = HashSet::new();
240-
for j in i..n {
241-
if set.contains(&nums[j]) {
242-
continue;
235+
let mut ans = Vec::new();
236+
let mut t = vec![0; n];
237+
let mut vis = vec![false; n];
238+
239+
fn dfs(
240+
nums: &Vec<i32>,
241+
t: &mut Vec<i32>,
242+
vis: &mut Vec<bool>,
243+
ans: &mut Vec<Vec<i32>>,
244+
i: usize,
245+
) {
246+
if i == nums.len() {
247+
ans.push(t.clone());
248+
return;
249+
}
250+
for j in 0..nums.len() {
251+
if vis[j] || (j > 0 && nums[j] == nums[j - 1] && !vis[j - 1]) {
252+
continue;
253+
}
254+
t[i] = nums[j];
255+
vis[j] = true;
256+
dfs(nums, t, vis, ans, i + 1);
257+
vis[j] = false;
243258
}
244-
set.insert(nums[j]);
245-
nums.swap(i, j);
246-
Self::dfs(i + 1, nums, res);
247-
nums.swap(i, j);
248259
}
249-
}
250260

251-
pub fn permute_unique(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
252-
let mut res = vec![];
253-
Self::dfs(0, &mut nums, &mut res);
254-
res
261+
dfs(&nums, &mut t, &mut vis, &mut ans, 0);
262+
ans
255263
}
256264
}
257265
```
258266

267+
#### JavaScript
268+
269+
```js
270+
/**
271+
* @param {number[]} nums
272+
* @return {number[][]}
273+
*/
274+
var permuteUnique = function (nums) {
275+
nums.sort((a, b) => a - b);
276+
const n = nums.length;
277+
const ans = [];
278+
const t = Array(n);
279+
const vis = Array(n).fill(false);
280+
const dfs = i => {
281+
if (i === n) {
282+
ans.push(t.slice());
283+
return;
284+
}
285+
for (let j = 0; j < n; ++j) {
286+
if (vis[j] || (j > 0 && nums[j] === nums[j - 1] && !vis[j - 1])) {
287+
continue;
288+
}
289+
t[i] = nums[j];
290+
vis[j] = true;
291+
dfs(i + 1);
292+
vis[j] = false;
293+
}
294+
};
295+
dfs(0);
296+
return ans;
297+
};
298+
```
299+
259300
#### C#
260301

261302
```cs

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

+71-30
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,16 @@ tags:
5454

5555
### Solution 1: Sorting + Backtracking
5656

57-
We can first sort the array, which allows us to place duplicate numbers together, making it easier for us to remove duplicates.
57+
We can first sort the array so that duplicate numbers are placed together, making it easier to remove duplicates.
5858

59-
Next, we design a function $dfs(i)$, indicating that we need to fill in the number at the $i$th position. The specific implementation of the function is as follows:
59+
Then, we design a function $\textit{dfs}(i)$, which represents the current number to be placed at the $i$-th position. The specific implementation of the function is as follows:
6060

61-
- If $i = n$, it means we have finished filling in, add the current permutation to the answer array, and then return.
62-
- Otherwise, we enumerate the number $nums[j]$ at the $i$th position, where the range of $j$ is $[0, n - 1]$. We need to ensure that $nums[j]$ has not been used and is different from the number enumerated before, so as to ensure that the current permutation is not repeated. If the conditions are met, we can fill in $nums[j]$, and continue to recursively fill in the next position, that is, call $dfs(i + 1)$. After the recursive call ends, we need to mark $nums[j]$ as unused for later enumeration.
61+
- If $i = n$, it means we have filled all positions, add the current permutation to the answer array, and then return.
62+
- Otherwise, we enumerate the number $nums[j]$ for the $i$-th position, where the range of $j$ is $[0, n - 1]$. We need to ensure that $nums[j]$ has not been used and is different from the previously enumerated number to ensure that the current permutation is not duplicated. If the conditions are met, we can place $nums[j]$ and continue to recursively fill the next position by calling $\textit{dfs}(i + 1)$. After the recursive call ends, we need to mark $nums[j]$ as unused to facilitate subsequent enumeration.
6363

64-
In the main function, we first sort the array, then call $dfs(0)$, that is, start filling from the 0th position, and finally return the answer array.
64+
In the main function, we first sort the array, then call $\textit{dfs}(0)$ to start filling from the 0th position, and finally return the answer array.
6565

66-
The time complexity is $O(n \times n!)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array. We need to enumerate $n!$ times, and each enumeration takes $O(n)$ time to judge whether it is repeated. In addition, we need a marker array to mark whether each position has been used, so the space complexity is $O(n)$.
66+
The time complexity is $O(n \times n!)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array. We need to perform $n!$ enumerations, and each enumeration requires $O(n)$ time to check for duplicates. Additionally, we need a marker array to mark whether each position has been used, so the space complexity is $O(n)$.
6767

6868
Similar problems:
6969

@@ -139,12 +139,12 @@ class Solution {
139139
class Solution {
140140
public:
141141
vector<vector<int>> permuteUnique(vector<int>& nums) {
142-
sort(nums.begin(), nums.end());
142+
ranges::sort(nums);
143143
int n = nums.size();
144144
vector<vector<int>> ans;
145145
vector<int> t(n);
146146
vector<bool> vis(n);
147-
function<void(int)> dfs = [&](int i) {
147+
auto dfs = [&](this auto&& dfs, int i) {
148148
if (i == n) {
149149
ans.emplace_back(t);
150150
return;
@@ -169,7 +169,7 @@ public:
169169
170170
```go
171171
func permuteUnique(nums []int) (ans [][]int) {
172-
sort.Ints(nums)
172+
slices.Sort(nums)
173173
n := len(nums)
174174
t := make([]int, n)
175175
vis := make([]bool, n)
@@ -201,8 +201,8 @@ function permuteUnique(nums: number[]): number[][] {
201201
nums.sort((a, b) => a - b);
202202
const n = nums.length;
203203
const ans: number[][] = [];
204-
const t: number[] = new Array(n);
205-
const vis: boolean[] = new Array(n);
204+
const t: number[] = Array(n);
205+
const vis: boolean[] = Array(n).fill(false);
206206
const dfs = (i: number) => {
207207
if (i === n) {
208208
ans.push(t.slice());
@@ -226,34 +226,75 @@ function permuteUnique(nums: number[]): number[][] {
226226
#### Rust
227227

228228
```rust
229-
use std::collections::HashSet;
230229
impl Solution {
231-
fn dfs(i: usize, nums: &mut Vec<i32>, res: &mut Vec<Vec<i32>>) {
230+
pub fn permute_unique(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
231+
nums.sort();
232232
let n = nums.len();
233-
if i == n {
234-
res.push(nums.clone());
235-
return;
236-
}
237-
let mut set = HashSet::new();
238-
for j in i..n {
239-
if set.contains(&nums[j]) {
240-
continue;
233+
let mut ans = Vec::new();
234+
let mut t = vec![0; n];
235+
let mut vis = vec![false; n];
236+
237+
fn dfs(
238+
nums: &Vec<i32>,
239+
t: &mut Vec<i32>,
240+
vis: &mut Vec<bool>,
241+
ans: &mut Vec<Vec<i32>>,
242+
i: usize,
243+
) {
244+
if i == nums.len() {
245+
ans.push(t.clone());
246+
return;
247+
}
248+
for j in 0..nums.len() {
249+
if vis[j] || (j > 0 && nums[j] == nums[j - 1] && !vis[j - 1]) {
250+
continue;
251+
}
252+
t[i] = nums[j];
253+
vis[j] = true;
254+
dfs(nums, t, vis, ans, i + 1);
255+
vis[j] = false;
241256
}
242-
set.insert(nums[j]);
243-
nums.swap(i, j);
244-
Self::dfs(i + 1, nums, res);
245-
nums.swap(i, j);
246257
}
247-
}
248258

249-
pub fn permute_unique(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
250-
let mut res = vec![];
251-
Self::dfs(0, &mut nums, &mut res);
252-
res
259+
dfs(&nums, &mut t, &mut vis, &mut ans, 0);
260+
ans
253261
}
254262
}
255263
```
256264

265+
#### JavaScript
266+
267+
```js
268+
/**
269+
* @param {number[]} nums
270+
* @return {number[][]}
271+
*/
272+
var permuteUnique = function (nums) {
273+
nums.sort((a, b) => a - b);
274+
const n = nums.length;
275+
const ans = [];
276+
const t = Array(n);
277+
const vis = Array(n).fill(false);
278+
const dfs = i => {
279+
if (i === n) {
280+
ans.push(t.slice());
281+
return;
282+
}
283+
for (let j = 0; j < n; ++j) {
284+
if (vis[j] || (j > 0 && nums[j] === nums[j - 1] && !vis[j - 1])) {
285+
continue;
286+
}
287+
t[i] = nums[j];
288+
vis[j] = true;
289+
dfs(i + 1);
290+
vis[j] = false;
291+
}
292+
};
293+
dfs(0);
294+
return ans;
295+
};
296+
```
297+
257298
#### C#
258299

259300
```cs

solution/0000-0099/0047.Permutations II/Solution.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
class Solution {
22
public:
33
vector<vector<int>> permuteUnique(vector<int>& nums) {
4-
sort(nums.begin(), nums.end());
4+
ranges::sort(nums);
55
int n = nums.size();
66
vector<vector<int>> ans;
77
vector<int> t(n);
88
vector<bool> vis(n);
9-
function<void(int)> dfs = [&](int i) {
9+
auto dfs = [&](this auto&& dfs, int i) {
1010
if (i == n) {
1111
ans.emplace_back(t);
1212
return;
@@ -24,4 +24,4 @@ class Solution {
2424
dfs(0);
2525
return ans;
2626
}
27-
};
27+
};

solution/0000-0099/0047.Permutations II/Solution.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
func permuteUnique(nums []int) (ans [][]int) {
2-
sort.Ints(nums)
2+
slices.Sort(nums)
33
n := len(nums)
44
t := make([]int, n)
55
vis := make([]bool, n)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @param {number[]} nums
3+
* @return {number[][]}
4+
*/
5+
var permuteUnique = function (nums) {
6+
nums.sort((a, b) => a - b);
7+
const n = nums.length;
8+
const ans = [];
9+
const t = Array(n);
10+
const vis = Array(n).fill(false);
11+
const dfs = i => {
12+
if (i === n) {
13+
ans.push(t.slice());
14+
return;
15+
}
16+
for (let j = 0; j < n; ++j) {
17+
if (vis[j] || (j > 0 && nums[j] === nums[j - 1] && !vis[j - 1])) {
18+
continue;
19+
}
20+
t[i] = nums[j];
21+
vis[j] = true;
22+
dfs(i + 1);
23+
vis[j] = false;
24+
}
25+
};
26+
dfs(0);
27+
return ans;
28+
};

0 commit comments

Comments
 (0)