LeetCode subsets

2020-12-21

https://leetcode-cn.com/problems/subsets

combination

Array#combination 内置的组合可以直接解出答案. 在 nums 中, 取 n 个数的组合. n 取 0 即空数组, n 最大取 nums.size 个.

Ruby

# @param {Integer[]} nums
# @return {Integer[][]}
def subsets(nums)
  results = []
  count = nums.size + 1
  count.times do |i|
    nums.combination(i).each { |item| results << item }
  end
  results
end

# res = subsets([1, 2, 3])
# p res, res.size

巧妙遍历

[]
[], [1]
[], [1], [2], [1, 2]
[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]

新的一次操作在上一次的基础上, 原样复制一份, 再在另外的一份加入n, 合并.

注意 Ruby Array#clone 是浅拷贝, 不能用在这里.

Ruby

# @param {Integer[]} nums
# @return {Integer[][]}
def subsets(nums)
  results = [[]]

  nums.each do |n|
    current_results_count = results.size
    current_results_count.times do |idx|
      results << results[idx] + [n]
    end
  end

  results
end

# res = subsets([1, 2, 3])
# p res, res.size

回溯法

特别注意 path, 他会在回溯的过程中改变, 赋值时应该使用他的拷贝值.

Ruby

# @param {Integer[]} nums
# @return {Integer[][]}
def subsets(nums)
  @results = []
  @nums = nums

  dfs([], 0)

  @results
end

def dfs(path, num_idx)
  @results << path + [] # generate new object, imitate deep array clone

  (num_idx...@nums.size).to_a.each do |i|
    path.push(@nums[i])
    dfs(path, i + 1)
    path.pop
  end
end

# res = subsets([1, 2, 3])
# p res, res.size

Golang

package main

import "fmt"

func main() {
	fmt.Println(subsets([]int{1, 2, 3}))
}

func subsets(nums []int) [][]int {
	results := make([][]int, 0)
	path := make([]int, 0)
	dfs(path, 0, &results, &nums)
	return results
}

func dfs(path []int, idx int, results *[][]int, nums *[]int) {
	pathClone := make([]int, len(path))
	copy(pathClone, path)
	*results = append(*results, pathClone) // use cloned array

	for i := idx; i < len(*nums); i++ {
		path = append(path, (*nums)[i]) // push
		dfs(path, i+1, results, nums)
		path = path[0 : len(path)-1] // pop
	}
}