# ARTS

ARTS 是陈浩（网名”左耳朵耗子“）在极客时间专栏里发起的一个活动，目的是通过分享的方式来坚持学习。

## 算法

### LeetCode 78 Subsets & 90 Subsets II

78.Subsets

``````Given a set of **distinct** integers, _nums_, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

Example:
Input: nums = [1,2,3]
Output:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]``````

``````func subsets(nums []int) [][]int {
sz := len(nums)
ans := &[][]int{}
// cmb := &[]int{}
cmb := make([]int, 0, sz)

for i := 0; i <= sz; i++ {
bt(i, 0, cmb, ans, nums)
}
return *ans
}

func bt(l, s int, cmb []int, ans *[][]int, nums []int) {
sz := len(nums)
if len(cmb) == l {
tmp := make([]int, len(cmb), len(cmb))
copy(tmp, cmb)
*ans = append(*ans, tmp)
return
}
for i := s; i < sz; i++ {
cmb = append(cmb, nums[i])
bt(l, i+1, cmb, ans, nums)
cmb = cmb[:len(cmb)-1]
}
}``````

90.Subsets

``````Given a collection of integers that might contain duplicates, **_nums_**, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

Example:
Input: [1,2,2]
Output:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]``````

78 题现有的回溯逻辑，可以很容易的对拥有相同前缀的子集进行判重。所以对原本 `bt` 函数中循环的位置：

``````for i := s; i < sz; i++ {
cmb = append(cmb, nums[i])
bt(l, i+1, cmb, ans, nums)
cmb = cmb[:len(cmb)-1]
}``````

``````    for i := s; i < sz; i++ {
if i > s && nums[i] == nums[i-1] {
continue
}
*cmb = append(*cmb, nums[i])
bt(nums, l, i+1, cmb, ans)
*cmb = (*cmb)[:len(*cmb)-1]
}``````

``````import(
"sort"
)

func subsetsWithDup(nums []int) [][]int {
ans := make([][]int, 0)
cmb := make([]int, 0)
sz := len(nums)

// 排序是为了把相同的数字放到一起，方便后面判重
sort.Slice(nums, func(i, j int) bool {
return nums[i] < nums[j]
})

for i := 0; i <= sz; i++ {
bt(nums, i, 0, &cmb, &ans)
}

return ans
}

func bt(nums []int, l, s int, cmb *[]int, ans *[][]int) {
sz := len(nums)
if l == len(*cmb) {
tmp := make([]int, len(*cmb), len(*cmb))
copy(tmp, *cmb)
*ans = append(*ans, tmp)
return
}
for i := s; i < sz; i++ {
if i > s && nums[i] == nums[i-1] {
continue
}
*cmb = append(*cmb, nums[i])
bt(nums, l, i+1, cmb, ans)
*cmb = (*cmb)[:len(*cmb)-1]
}
}``````

## 两个 Golang 中 slice 的技巧

``````    if len(cmb) == l {
tmp := make([]int, len(cmb), len(cmb))
copy(tmp, cmb)
*ans = append(*ans, tmp)
return
}``````

### 二维 slcie 追加时可能会遇到的一个”坑“

``````    if len(cmbreflect.DeepEqual(ans[i], ans[j])) == l {
*ans = append(*ans, cmb)
return
}``````

### Golang 中的 slice 是否可以比较

”， 在 slice 是否相同这个问题上不可避免的产生了歧义：

there are multiple considerations involving shallow vs. deep comparison, pointer vs. value comparison, how to deal with recursive types, and so on.

``````import "reflect"

reflect.DeepEqual(ans[i], ans[j])``````

`DeepEqual` 对 slice 进行的“深度”比较将会判断两个 slice 的底层数组地址是否相同，或者两个 slice 的每一个元素都是否相同。当然这个方法不仅能比较 slice，具体可以看官方文档的介绍

45 声望
6 粉丝
0 条评论