代码随想录算法训练营第二十五天 | 216.组合总和III,17.电话号码的字母组合 [回溯篇]

代码随想录算法训练营第二十五天


LeetCode 216.组合总和III

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

文章讲解:代码随想录#216.组合总和III

视频讲解:回溯算法如何剪枝?| LeetCode:216.组合总和III

题目描述

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

  • 只使用数字1到9
  • 每个数字最多 使用一次
    返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例1

输入:k = 3, n = 7

输出: [[1,2,4]]

解释:

1 + 2 + 4 = 7

没有其他符合的组合了。

示例2

输入:k = 3, n = 9

输出: [[1,2,6], [1,3,5], [2,3,4]]

解释:

1 + 2 + 6 = 9

1 + 3 + 5 = 9

2 + 3 + 4 = 9

没有其他符合的组合了。

提示

  • 2 <= k <= 9
  • 1 <= n <= 60

思路

在数字1到9之间找到k个数,其和为n,并且保证每个数字只能使用一次。

如果使用k个for循环遍历数字,明显不太合适,所以此题应使用回溯法来求解。

k表示递归的次数,也就是树的深度。

数字1到9表示每次遍历树的宽度,题中要求每个数字只使用一次,所以每次递归时需要考虑遍历1到9的索引。

回溯的终止条条件为数的和为n。

在遍历的过种中也可以考虑如下的剪枝操作:

①当数和已经大于n了,退出当前循环。

②当剩余的数字少于还需要的数字个数时,for循环结束。

参考代码

c 复制代码
int sum, cnt;
int** res;
typedef struct {
    int index;
    int nums[10];
} Data;

Data data = {0};

void backtracking(int k, int n, int idx) {
    if (data.index == k) {
        if (sum == n) { // 符合条件,记录数据
            res[cnt] = malloc(k * sizeof(int));
            for (int i = 0; i < k; i++)
                res[cnt][i] = data.nums[i];
            cnt++;
        }
        return;
    }

	// 剪枝二:保证剩余数字个数大于等于还需要的数字个数
    for (int i = idx; i <= 9 - (k - data.index) + 1; i++) {
        if (sum + i > n)
            break; // 剪枝一:如果sum+i大于n,直接跳出for循环
        sum += i;
        data.nums[data.index++] = i;
        backtracking(k, n, i + 1);
        sum -= i; // 回溯
        data.index--;
        data.nums[data.index] = 0;
    }
}

int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes) {
    res = (int**)malloc(100 * sizeof(int*));
    sum = 0;
    cnt = 0;

    backtracking(k, n, 1);

    *returnSize = cnt;
    *returnColumnSizes =
        (int*)malloc(sizeof(int) * cnt); // 需要给returnColumnSizes分配内存
    for (int i = 0; i < cnt; i++) {
        (*returnColumnSizes)[i] = k;
    }
    return res;
}

总结

  1. 这道题相对 LeetCode 77.组合 多了一个条件,需要找出和为n的k个数的组合,整个集合是固定的,相对来说也比较简单。

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

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

文章讲解:代码随想录#17.电话号码的字母组合

视频讲解:还得用回溯算法!| LeetCode:17.电话号码的字母组合

题目描述

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例1

输入:digits = "23"

输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例2

输入:digits = ""

输出:[]

示例3

输入:digits = "2"

输出:["a","b","c"]

提示

  • 0 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字。

思路

这道题关键是需要构建一个数字与字母转换的表,如:

[2] = ["abc"]

[3] = ["def"]

...

对于示例1来说,输入了两个数字2和3,树的深度为2。

首先遍历数字2,从转换表中取出字符串"abc",

然后先遍历a,将a存起来,(第一层)

调用递归函数,在递归函数中,遍历数字3...(第二层)

退出递归函数后,进行回溯操作,

接着再遍历b,将b存起来,

...

直到遍历完c后(遍历树的宽度)。

可以构建一个递归函数,返回值为void,参数有两个人,一个是输入的字符串,一个是当前遍历层级。

递归函数的终止条件是digits取完所有的数字(代表递归的次数,也是树的深度)。

参考代码

c 复制代码
char **res;
int cnt;
typedef struct {
    int index;
    char str[5];
}Data;
Data data = {0};

char *convert[] = {
    "", // 0
    "", // 1
    "abc", // 2
    "def", // 3
    "ghi", // 4
    "jkl", // 5
    "mno", // 6
    "pqrs", // 7
    "tuv", // 8
    "wxyz", // 9
};

void backtracking(char *src, int level)
{
    if (strlen(src) == level) {
        res[cnt] = (char*)malloc(sizeof(char) * (data.index + 1));        
        strcpy(res[cnt++], data.str);
        return; 
    }

    char *s = convert[src[level] - '0'];
    int len = strlen(s);
    for (int i = 0; i < len; i++) {
        data.str[data.index++] = s[i];
        backtracking(src, level + 1);
        data.index--; // 回溯
        data.str[data.index] = '\0';
    }
}

char** letterCombinations(char* digits, int* returnSize) {
    if (strlen(digits) == 0) {
        *returnSize = 0;
        return NULL;
    }

    res = (char**)malloc(1000 * sizeof(char*));
    cnt = 0;    

    backtracking(digits, 0);
    *returnSize = cnt;
    return res;
}
相关推荐
爱是小小的癌3 分钟前
Java-数据结构-优先级队列(堆)
java·前端·数据结构
sjsjs118 分钟前
【数据结构-字典树】力扣14. 最长公共前缀
数据结构·leetcode
python算法(魔法师版)26 分钟前
基于机器学习鉴别中药材的方法
深度学习·线性代数·算法·机器学习·支持向量机·数据挖掘·动态规划
摘星崖1 小时前
1.3编译流程与调试基础
c语言
南玖yy1 小时前
C语言:结构体
c语言·开发语言
代码对我眨眼睛1 小时前
重回C语言之老兵重装上阵(十三)C 预处理器
linux·c语言
JNU freshman1 小时前
力扣第435场周赛讲解
算法·leetcode·蓝桥杯
眼镜哥(with glasses)2 小时前
蓝桥杯python基础算法(2-2)——基础算法(B)——模拟(上)
算法
赵鑫亿3 小时前
7.DP算法
算法·dp
南玖yy3 小时前
C语言:整型提升
c语言·开发语言