[LeetCode题解]216. 组合总和 III

前言

看完这篇题解,可以再看看这几个问题:

题目描述

216. 组合总和 III

题目:216. 组合总和 III

解题思路

本题与 39. 组合总和40. 组合总和 II 类似,解法一样,主要区别在于剪枝或去重的条件上。

[39. 组合总和]

剪枝:target-candidates[i] < 0 表示结果集加上 candidates[i] 将超过 target,不符合条件,剪掉。

[40. 组合总和 II]

剪枝条件与上一题一样,主要是去重的条件:i > start && candidates[i] == candidates[i-1]

[216. 组合总和 III]

剪枝条件有两个情况,一种跟上两题相同:n - i < 0 ;另一种是:k == 1 && n-i > 0

算法步骤:

  1. 排序。方便进行剪枝判断。
  2. 回溯。排列、组合类题目常用方法。
  3. 剪枝。提前去掉不符合的结果,降低时间复杂度。
  4. 去重。

代码实现

var ans [][]int // 结果集
var list []int // 临时结果集

func combinationSum3(k int, n int) [][]int {
    /*  
        回溯 + 剪枝 + 去重
        剪枝条件: > k 去掉
        去重条件: 加 start 控制
    */
    ans = make([][]int, 0)
    list = make([]int, 0)
    backtarck(k, n, 1)
    return ans
}

func backtarck(k int, n int, start int) {
    if n == 0 && k == 0 {
        tmp := make([]int, len(list))
        copy(tmp, list)
        ans = append(ans, tmp)
        return
    }

    for i:=start;i<=9;i++ {
        if n - i < 0 {
            break
        }
        if k == 1 && n-i > 0 {
            continue
        }
        list = append(list, i)
        backtarck(k-1, n-i, i+1)
        list = list[:len(list)-1]
    }
}

复杂度分析:

  • 时间复杂度:\(O(2^n * n)\)。一般的递归树的时间复杂度是 \(O(2^n)\),遍历 n 的时间复杂度是 \(O(n)\) ,最终时间复杂度为 \(O(2^n * n)\)
  • 空间复杂度:\(O(n)\)。除了保存结果的数组外,还需要一个数组保存回溯过程的中间结果。
posted @ 2020-09-11 17:08  大杂草  阅读(128)  评论(0编辑  收藏  举报