算法训练第19天|77. 组合|216.组合总和III|17.电话号码的字母组合

LeetCode 77. 组合

题目链接:77. 组合

题目讲解:代码随想录

题目描述:给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。

本题是回溯法的经典题目。

使用回溯:

  • 递归函数的返回值以及参数,函数里一定有两个参数,集合n里面取k个数,还需要一个参数startIndex用来记录本层递归的中,集合从哪里开始遍历。
  •  回溯函数终止条件,path这个数组的大小如果达到k,说明我们找到了一个子集大小为k的组合了。
  • 单层搜索的过程,for循环每次从startIndex开始遍历,然后用path保存取到的节点i,backtracking(递归函数)通过不断调用自己一直往深处遍历,然后就是回溯的操作。

可以进行剪枝操作,如果for循环选择的起始位置之后的元素个数已经不足我们需要的元素个数了,那么就没有必要搜索了

func combine(n int, k int) [][]int {
    path := []int{}
    res := [][]int{}
    var backtracking func(n, k, start int)

    backtracking = func(n, k, start int){
        if len(path) == k{ // 说明已经满足了k个数的要求
            tmp := make([]int, k)
            copy(tmp, path)
            res = append(res, tmp)
            return 
        }

        for i := start; i <= n; i++{ // 从start开始,不往回走,避免出现重复组合
            if n - i + 1 < k - len(path){ // 剪枝
                break
            }

            path = append(path, i)
            backtracking(n, k, i+1)
            path = path[:len(path)-1] // 回溯
        }
    }

    backtracking(n, k, 1)
    return res
}

LeetCode 216.组合总和III

题目链接:216.组合总和III

题目讲解:代码随想录

题目描述:找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

  • 只使用数字1到9
  • 每个数字 最多使用一次 

返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

  •  确定递归函数参数,函数里一定有两个参数,集合n里面取k个数,还需要一个参数startIndex用来记录本层递归的中,集合从哪里开始遍历,还需要sum记录目前为止的和是多少。
  •  回溯函数终止条件,如果此时path里收集到的元素和(sum) 和targetSum(就是题目描述的n)相同了,就用result收集当前的结果。
  • 单层搜索的过程,for循环每次从startIndex开始遍历,然后用path保存取到的节点i,backtracking(递归函数)通过不断调用自己一直往深处遍历,然后就是回溯的操作。

可以进行剪枝操作

func combinationSum3(k int, n int) [][]int {
    path := []int{}
    res := [][]int{}

    var backtracking func(k, n, start, sum int)

    backtracking = func(k, n, start, sum int){
        if len(path) == k{
            if sum == n{
                tmp := make([]int, k)
                copy(tmp, path)
                res = append(res, tmp)
            }
            return 
        }

        for i := start; i <= 9; i++{
            if sum > n || n - i + 1 < k - len(path){
                break
            }

            path = append(path, i)
            backtracking(k, n, i+1, sum+i)
            path = path[:len(path)-1]
        }
    }

    backtracking(k, n, 1, 0)
    return res
}

LeetCode 17.电话号码的字母组合

题目链接:17.电话号码的字母组合

题目讲解:代码随想录

题目描述:给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

使用map来记录数字对应的字母串

  •  确定递归函数参数,参数指定是有题目中给的string digits,然后还要有一个参数就是int型的start。
  •  回溯函数终止条件,那么终止条件就是如果start等于 输入的数字个数(digits.size)了,然后收集结果,结束本层递归。
  • 单层搜索的过程,首先要取start指向的数字,并找到对应的字符集(手机键盘的字符集)。然后for循环来处理这个字符集。用path保存取到的节点i对应字母,backtracking(递归函数)通过不断调用自己一直往深处遍历,然后就是回溯的操作。
func letterCombinations(digits string) []string {
    m := []string{"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}

    res := []string{}
    path := []byte{}

    var backtracking func(digits string, start int)
    backtracking = func(digits string, start int){
        if len(path) == len(digits){
            tmp := string(path)
            res = append(res, tmp)
            return
        }

        digit := int(digits[start] - '0') // 获取到输入的数字
        str := m[digit-2] // 获取到数字对应的 字母串
        for j := 0; j < len(str); j++{
            path = append(path, str[j])
            backtracking(digits, start+1)
            path = path[:len(path)-1] // 回溯
        }
    }

    if digits == ""{
        return res
    }
    backtracking(digits, 0)
    return res
}
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值