组合

Posted by zhouqian on Tuesday, August 9, 2022

力扣 77. 组合

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。


方案一:递归,遍历每一种可能。

func combine(n int, k int) (ans [][]int) {
    // 当前选中的元素
    chosen := make([]int, 0, k)
    // 递归函数
    var recur func(i int)
    recur = func(i int) {
        // 如果长度达到 k,则做 chosen 的深拷贝,将结果保存
        if len(chosen) == k  {
            tmp := make([]int, k)
            copy(tmp, chosen)
            ans = append(ans, tmp)
            return
        }
        // 如果余下的元素不足以满足 k 个数子的组合则直接返回
        if len(chosen) + (n - i + 1) < k {
            return
        }

        // 不选当前元素进行下一轮递归
        recur(i + 1)
        // 选择当前元素进行下一轮递归
        chosen = append(chosen, i)
        recur(i + 1)
        // 还原现场,防止当前递归分支的变动影响到相邻分支
        chosen = chosen[:len(chosen) - 1]
    }

    // 从元素 1 开始递归
    recur(1)
    return
}
  • 时间复杂度:O(k * n!/(m! * (n - m)!)),因为一共有 n!/(m! * (n - m)!) 个状态,每个状态需要 O(k) 的时间复杂度(深拷贝),所以时间复杂度为 O(k * n!/(m! * (n - m)!))。
  • 空间复杂度:O(k + n),因为栈深度为 n,chosen 长度为 k ,所以空间复杂度为 O(n + k)。