Skip to content

Commit d83478e

Browse files
committed
feat: 0078. Subsets
1 parent 264f52b commit d83478e

File tree

4 files changed

+310
-3
lines changed

4 files changed

+310
-3
lines changed

Leetcode/0078.Subsets/README.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
title: 0078. Subsets
3+
subtitle: "https://leetcode.com/problems/subsets/description/"
4+
date: 2023-11-21T17:30:00+08:00
5+
lastmod: 2023-11-21T17:30:00+08:00
6+
draft: false
7+
author: "Kimi.Tsai"
8+
authorLink: "https://kimi0230.github.io/"
9+
description: "0078.Subsets"
10+
license: ""
11+
images: []
12+
13+
tags: [LeetCode, Go, Medium, Subsets]
14+
categories: [LeetCode]
15+
16+
featuredImage: ""
17+
featuredImagePreview: ""
18+
19+
hiddenFromHomePage: false
20+
hiddenFromSearch: false
21+
twemoji: false
22+
lightgallery: true
23+
ruby: true
24+
fraction: true
25+
fontawesome: true
26+
linkToMarkdown: false
27+
rssFullText: false
28+
29+
toc:
30+
enable: true
31+
auto: true
32+
code:
33+
copy: true
34+
maxShownLines: 200
35+
math:
36+
enable: false
37+
# ...
38+
mapbox:
39+
# ...
40+
share:
41+
enable: true
42+
# ...
43+
comment:
44+
enable: true
45+
# ...
46+
library:
47+
css:
48+
# someCSS = "some.css"
49+
# located in "assets/"
50+
# Or
51+
# someCSS = "https://cdn.example.com/some.css"
52+
js:
53+
# someJS = "some.js"
54+
# located in "assets/"
55+
# Or
56+
# someJS = "https://cdn.example.com/some.js"
57+
seo:
58+
images: []
59+
# ...
60+
---
61+
# [0078. Subsets](https://leetcode.com/problems/subsets/description/)
62+
63+
## 題目
64+
Given an integer array nums of unique elements, return all possible
65+
subsets
66+
(the power set).
67+
68+
The solution set must not contain duplicate subsets. Return the solution in any order.
69+
70+
71+
72+
Example 1:
73+
74+
Input: nums = [1,2,3]
75+
Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
76+
Example 2:
77+
78+
Input: nums = [0]
79+
Output: [[],[0]]
80+
81+
82+
Constraints:
83+
84+
1 <= nums.length <= 10
85+
-10 <= nums[i] <= 10
86+
All the numbers of nums are unique.
87+
88+
## 題目大意
89+
給定一組不含重複元素的整數陣列 nums,返回該陣列所有可能的子集(冪集)。 說明:解集不能包含重複的子集。
90+
91+
## 解題思路
92+
找出一個集合中的所有子集,空集也算是子集。 且陣列中的數位不會出現重複。 用 DFS 暴力枚舉即可。
93+
這一題和第 90 題,第 491 題類似,可以一起解答和複習
94+
95+
## Big O
96+
時間複雜 : `O(n^2)`
97+
空間複雜 : `O(n)`
98+
99+
## 來源
100+
* https://leetcode.com/problems/subsets/description/
101+
* https://leetcode.cn/problems/subsets/description/
102+
* https://books.halfrost.com/leetcode/ChapterFour/0001~0099/0078.Subsets/
103+
* https://github.com/suntong/lang/blob/master/lang/Go/src/ds/Recursion/LC-0B-Subsets-2.go
104+
105+
## 解答
106+
https://github.com/kimi0230/LeetcodeGolang/blob/master/Leetcode/0078.Subsets/main.go
107+
108+
```go
109+
package subsets
110+
111+
// 時間複雜 O(n^2) , 空間複雜 O(n)
112+
func Subsets(nums []int) [][]int {
113+
path, result := []int{}, [][]int{}
114+
for i := 0; i <= len(nums); i++ {
115+
genSubsets(nums, i, 0, path, &result)
116+
}
117+
return result
118+
}
119+
120+
func genSubsets(nums []int, elemSize, start int, path []int, result *[][]int) {
121+
if len(path) == elemSize {
122+
b := make([]int, len(path))
123+
copy(b, path)
124+
*result = append(*result, b)
125+
return
126+
}
127+
128+
for k := start; k < len(nums); k++ {
129+
path = append(path, nums[k])
130+
genSubsets(nums, elemSize, k+1, path, result)
131+
path = path[:len(path)-1]
132+
}
133+
}
134+
135+
// 時間複雜 O(n^2) , 空間複雜 O(n)
136+
func SubsetsDFS(nums []int) [][]int {
137+
path, result := []int{}, [][]int{}
138+
genSubsetsDFS(nums, path, &result)
139+
return result
140+
}
141+
142+
func genSubsetsDFS(nums []int, path []int, result *[][]int) {
143+
b := make([]int, len(path))
144+
copy(b, path)
145+
*result = append(*result, b)
146+
for i := 0; i < len(nums); i++ {
147+
// n個 element 在slice中
148+
genSubsetsDFS(nums[i+1:], append(path, nums[i]), result)
149+
}
150+
}
151+
152+
```
153+
154+
## Benchmark
155+
156+
```sh
157+
go test -benchmem -run=none LeetcodeGolang/Leetcode/0354.Russian-Doll-Envelopes -bench=. -cover
158+
goos: darwin
159+
goarch: amd64
160+
pkg: LeetcodeGolang/Leetcode/0354.Russian-Doll-Envelopes
161+
cpu: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
162+
BenchmarkMaxEnvelopes-8 7799131 160.3 ns/op 88 B/op 3 allocs/op
163+
BenchmarkMaxEnvelopes2-8 5800399 195.6 ns/op 80 B/op 4 allocs/op
164+
PASS
165+
coverage: 96.0% of statements
166+
ok LeetcodeGolang/Leetcode/0354.Russian-Doll-Envelopes 3.726s
167+
```

Leetcode/0078.Subsets/main.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package subsets
2+
3+
// 時間複雜 O(n^2) , 空間複雜 O(n)
4+
func Subsets(nums []int) [][]int {
5+
path, result := []int{}, [][]int{}
6+
for i := 0; i <= len(nums); i++ {
7+
genSubsets(nums, i, 0, path, &result)
8+
}
9+
return result
10+
}
11+
12+
func genSubsets(nums []int, elemSize, start int, path []int, result *[][]int) {
13+
if len(path) == elemSize {
14+
b := make([]int, len(path))
15+
copy(b, path)
16+
*result = append(*result, b)
17+
return
18+
}
19+
20+
for k := start; k < len(nums); k++ {
21+
path = append(path, nums[k])
22+
genSubsets(nums, elemSize, k+1, path, result)
23+
path = path[:len(path)-1]
24+
}
25+
}
26+
27+
// 時間複雜 O(n^2) , 空間複雜 O(n)
28+
func SubsetsDFS(nums []int) [][]int {
29+
path, result := []int{}, [][]int{}
30+
genSubsetsDFS(nums, path, &result)
31+
return result
32+
}
33+
34+
func genSubsetsDFS(nums []int, path []int, result *[][]int) {
35+
b := make([]int, len(path))
36+
copy(b, path)
37+
*result = append(*result, b)
38+
for i := 0; i < len(nums); i++ {
39+
// n個 element 在slice中
40+
genSubsetsDFS(nums[i+1:], append(path, nums[i]), result)
41+
}
42+
}

Leetcode/0078.Subsets/main_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package subsets
2+
3+
import (
4+
"reflect"
5+
"sort"
6+
"testing"
7+
)
8+
9+
var tests = []struct {
10+
arg1 []int
11+
want [][]int
12+
}{
13+
{
14+
[]int{1, 2, 3},
15+
[][]int{
16+
{}, {1}, {1, 2}, {1, 2, 3}, {1, 3}, {2}, {2, 3}, {3},
17+
},
18+
},
19+
{
20+
[]int{0},
21+
[][]int{
22+
{}, {0},
23+
},
24+
},
25+
}
26+
27+
func TestSubsets(t *testing.T) {
28+
for _, tt := range tests {
29+
got := Subsets(tt.arg1)
30+
sortOutput(&got)
31+
if !reflect.DeepEqual(got, tt.want) {
32+
// // if got := Subsets(tt.arg1); got != tt.want {
33+
t.Errorf("got = %v, want = %v", got, tt.want)
34+
}
35+
}
36+
}
37+
38+
//go:cover
39+
func TestSubsetsDFS(t *testing.T) {
40+
for _, tt := range tests {
41+
got := SubsetsDFS(tt.arg1)
42+
sortOutput(&got)
43+
44+
if !reflect.DeepEqual(got, tt.want) {
45+
// // if got := Subsets(tt.arg1); got != tt.want {
46+
t.Errorf("got = %v, want = %v", got, tt.want)
47+
}
48+
}
49+
}
50+
51+
func BenchmarkSubsets(b *testing.B) {
52+
b.ResetTimer()
53+
for i := 0; i < b.N; i++ {
54+
Subsets(tests[0].arg1)
55+
}
56+
}
57+
58+
func BenchmarkSubsetsDFS(b *testing.B) {
59+
b.ResetTimer()
60+
for i := 0; i < b.N; i++ {
61+
SubsetsDFS(tests[0].arg1)
62+
}
63+
}
64+
65+
// sorting [][]int{}
66+
func sortOutput(output *[][]int) {
67+
for i := range *output {
68+
sort.Ints((*output)[i])
69+
}
70+
sort.Slice(*output, func(i, j int) bool {
71+
return lexicoOrder(&(*output)[i], &(*output)[j])
72+
})
73+
}
74+
75+
func lexicoOrder(a, b *[]int) bool {
76+
for i := 0; i < len(*a) && i < len(*b); i++ {
77+
if (*a)[i] < (*b)[i] {
78+
return true
79+
} else if (*a)[i] > (*b)[i] {
80+
return false
81+
}
82+
}
83+
return len((*a)) < len((*b))
84+
}
85+
86+
/*
87+
go test -benchmem -run=none LeetcodeGolang/Leetcode/0354.Russian-Doll-Envelopes -bench=. -cover
88+
goos: darwin
89+
goarch: amd64
90+
pkg: LeetcodeGolang/Leetcode/0354.Russian-Doll-Envelopes
91+
cpu: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
92+
BenchmarkMaxEnvelopes-8 7799131 160.3 ns/op 88 B/op 3 allocs/op
93+
BenchmarkMaxEnvelopes2-8 5800399 195.6 ns/op 80 B/op 4 allocs/op
94+
PASS
95+
coverage: 96.0% of statements
96+
ok LeetcodeGolang/Leetcode/0354.Russian-Doll-Envelopes 3.726s
97+
*/

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,10 @@ def backtrack(路徑, 選擇列表):
151151
撤銷選擇(後序)
152152
```
153153

154-
| No. | Title | Solution | Difficulty | Time | Space | Topic |
155-
|-------------------------------------------------------------------------------|:--------------------------------------------------------------------:|:---------------------------------------------------------------------------------------:|------------|------|-------|--------------|
156-
| [0046](https://kimi0230.github.io/LeetcodeGolang/Leetcode/0046.Permutations/) | [Permutations (全排列)](https://leetcode.com/problems/permutations/) | [Go](https://github.com/kimi0230/LeetcodeGolang/tree/master/Leetcode/0046.Permutations) | Medium | O(n) | O(n) | Backtracking |
154+
| No. | Title | Solution | Difficulty | Time | Space | Topic |
155+
|-------------------------------------------------------------------------------|:--------------------------------------------------------------------:|:---------------------------------------------------------------------------------------:|------------|--------|-------|--------------|
156+
| [0046](https://kimi0230.github.io/LeetcodeGolang/Leetcode/0046.Permutations/) | [Permutations (全排列)](https://leetcode.com/problems/permutations/) | [Go](https://github.com/kimi0230/LeetcodeGolang/tree/master/Leetcode/0046.Permutations) | Medium | O(n) | O(n) | Backtracking |
157+
| [0078](https://kimi0230.github.io/LeetcodeGolang/Leetcode/0078.Subsets/) | [Subsets](https://leetcode.com/problems/subsets/) | [Go](https://github.com/kimi0230/LeetcodeGolang/tree/master/Leetcode/0078.Subsets) | Medium | O(n^2) | O(n) | Backtracking |
157158

158159
---
159160

0 commit comments

Comments
 (0)