24暑假算法刷题 | Day22 | LeetCode 77. 组合,216. 组合总和 III,17. 电话号码的字母组合

server/2024/11/15 6:18:22/

目录

  • 77. 组合
    • 题目描述
    • 题解
  • 216. 组合总和 III
    • 题目描述
    • 题解
  • 17. 电话号码的字母组合
    • 题目描述
    • 题解


77. 组合

点此跳转题目链接

题目描述

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

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

示例 1:

输入:n = 4, k = 2
输出:
[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4],
]

示例 2:

输入:n = 1, k = 1
输出:[[1]]

提示:

  • 1 <= n <= 20
  • 1 <= k <= n

题解

参考:代码随想录-77.组合 ,讲得非常细了。

算是回溯算法的入门题目,核心要理解回溯的树形结构,以及其中的横向纵向遍历逻辑:

img

然后,考虑回溯三部曲

1️⃣ 处理

本题就是很基础的求组合,所以每次往当前组合 path 添加新数字就好了:

path.push_back(i); 

当前组合名称取为 path ,旨在呼应回溯树形结构图中的纵向“探索”路线(先取一个数x,再取一个数y)

2️⃣ 递归

递归出口是经典的——当前组合大小达到目标组合大小,则将其加入结果集:

if (path.size() == k)
{res.push_back(path);return;
}

否则,当前位置数字确定后,递归下一个位置的数来做组合:

backTracking(i + 1, end, k)

3️⃣ 回溯

弹出当前组合的最后一个值,以便探索该位置的其他可能值:

path.pop_back();   

整体代码如下:

C++

class Solution
{
private:vector<int> path;vector<vector<int>> res;public:void backTracking(int start, int end, int k){// 回溯出口:子结果path已满(纵向遍历)if (path.size() == k){res.push_back(path);return;}// 横向遍历for (int i = start; i <= end; i++){path.push_back(i);           // 处理backTracking(i + 1, end, k); // 递归path.pop_back();             // 回溯}}vector<vector<int>> combine(int n, int k){backTracking(1, n, k);return res;}
};

Go

type Helper struct {path []intres  [][]int
}func (helper *Helper) backTracking(start int, end int, k int) {// 递归出口if len(helper.path) == k {// newPath := make([]int, len(helper.path))// copy(newPath, helper.path)// helper.res = append(helper.res, newPath)helper.res = append(helper.res, append([]int(nil), helper.path...))return}// 横向遍历for i := start; i <= end; i++ {helper.path = append(helper.path, i)           // 处理helper.backTracking(i+1, end, k)               // 递归helper.path = helper.path[:len(helper.path)-1] // 回溯}
}func combine(n int, k int) [][]int {helper := Helper{}helper.backTracking(1, n, k)return helper.res
}

216. 组合总和 III

点此跳转题目链接

题目描述

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

  • 只使用数字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
没有其他符合的组合了。

示例 3:

输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

提示:

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

题解

参考:代码随想录-216

回溯算法解决。首先想清楚回溯的树形结构图:

在这里插入图片描述

然后走回溯三部曲

  • 处理: 将当前处理的数字加入当前组合 path ,并求此时组合中的数字和

    进行这一步之前可以剪枝:由于是从1到9(从小到大)横向遍历,如果 目标和 与 当前和 的差小于即将加入的数字,说明再加数字必将导致组合总和过大,故没必要在此基础上往后遍历处理了。

  • 递归: 递归地尝试将后面的数字加入组合;递归出口: path 的大小达到目标大小 k ,且其中数字和等于目标和,则将 path 加入结果集

  • 回溯: 弹出当前组合的最后一个数,以便探索该位置放其他数的可能

代码如下:

class Solution
{
private:vector<int> path;vector<vector<int>> res;public:void backTracking(int start, int end, int maxPathSize, int targetSum, int curSum){// 递归出口(纵向遍历)if (path.size() == maxPathSize){if (curSum == targetSum)res.push_back(path);return;}// 剪枝if (targetSum - curSum < start)return;// 横向遍历for (int i = start; i <= end; i++){curSum += i;path.push_back(i);                                        // 处理backTracking(i + 1, end, maxPathSize, targetSum, curSum); // 递归curSum -= i;path.pop_back(); // 回溯}}vector<vector<int>> combinationSum3(int k, int n){backTracking(1, 9, k, n, 0);return res;}
};

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'] 的一个数字。

题解

参考:代码随想录-17

回溯算法解决。首先想清楚回溯的树形结构图:

在这里插入图片描述

然后走回溯三部曲

  • 处理: 从当前处理的数字对应的字母串中,取一个字母加入当前组合(字符串) path

  • 递归: 递归地尝试将后面的数字对应的可能字母加入组合;递归出口: path 的长度与所给数字串 digits 相同,则将 path 加入结果集

  • 回溯: 弹出当前组合的最后一个字符,以便探索该位置放其他字母的可能

c++代码如下:

class Solution
{
private:string path = "";vector<string> res;unordered_map<char, string> dict = {{'2', "abc"},{'3', "def"},{'4', "ghi"},{'5', "jkl"},{'6', "mno"},{'7', "pqrs"},{'8', "tuv"},{'9', "wxyz"}};public:void backTracking(const string &digits, int start){// 递归出口if (path.length() == digits.length()){res.push_back(path);return;}char digit = digits[start];   // 当前要处理的数字string letters = dict[digit]; // 当前处理数字对应的字母// 横向遍历for (int i = 0; i < letters.length(); i++){path.push_back(letters[i]);      // 处理backTracking(digits, start + 1); // 递归path.pop_back();                 // 回溯}}vector<string> letterCombinations(string digits){if (digits == "")return res;backTracking(digits, 0);return res;}
};

顺便再熟悉下golang:

type Helper struct {path stringres  []stringdict map[byte]string
}func newHelper() *Helper {return &Helper{dict: map[byte]string{'2': "abc",'3': "def",'4': "ghi",'5': "jkl",'6': "mno",'7': "pqrs",'8': "tuv",'9': "wxyz",},}
}func (helper *Helper) backTracking(digits string, start int) {// 递归出口if len(helper.path) == len(digits) {helper.res = append(helper.res, helper.path)return}letters := helper.dict[digits[start]]for _, letter := range letters {helper.path = helper.path + string(letter)     // 处理helper.backTracking(digits, start+1)           // 递归helper.path = helper.path[:len(helper.path)-1] // 回溯}
}func letterCombinations(digits string) []string {helper := newHelper()if len(digits) == 0 {return helper.res}helper.backTracking(digits, 0)return helper.res
}

http://www.ppmy.cn/server/90702.html

相关文章

php、mantis、showDoc部署

下载软件安装包:Mantis Bug Tracker 下载vs包&#xff1a;https://www.microsoft.com/en-us/download/details.aspx?id48145,解决“因为计算机中丢失msvcr110.dll”下载apache服务器:Apache VS17 binaries and modules download下载php:PHP For Windows: Binaries and source…

vuex学习day03-辅助函数mapActions、getters、模块module、分模块后的访问(均需要开启命名空间)

8、actions续 &#xff08;3&#xff09;辅助函数mapActions 1&#xff09;作用&#xff1a;提取actions中的方法&#xff0c;映射到组件的methods中 2&#xff09;语法 已知&#xff1a; ①导入 ②展开映射 ③使用 效果&#xff1a; 9、getters &#xff…

机器学习西瓜书笔记(四) 第四章决策树

第四章 第4章 决策树4.1 基本流程小结4.2 划分选择4.2.1 信息增益第4章 决策树 4.1 基本流程 决策树(decision tree)是一种常见的机器学习方法。以二分类任务西瓜分类为例,我们可以得到一个如图的决策树: 上面这棵决策树可以参考数据结构的二叉树,理解起来很简单。 一般…

构建稳固与安全的网络环境:从微软蓝屏事件中的教训学习

近日&#xff0c;一场由微软视窗系统软件更新引发的全球性“微软蓝屏”事件震惊了整个科技界。这次事件不仅暴露了现代IT基础设施在面对大规模软件缺陷时的脆弱性&#xff0c;也引发了对网络安全与系统稳定性的深刻思考。在本文中&#xff0c;我们将探讨这次事件的根源、影响以…

Typescript配置文件(tsconfig.json)详解系列五:allowArbitraryExtensions

前言 本文使用的Typescript版本为5.5.2 配置 {compilerOptions: {"allowArbitraryExtensions": true} }说明 allowArbitraryExtensions是typescript5.x后加入的字段&#xff0c;允许我们可以导入任何后缀名的文件。 并且我们必须要有一个和这个文件配套的类型声明…

React前端面试每日一试 3.状态(State)和属性(Props)的区别是什么?

加粗样式先简单介绍一下Props和State的特点 Props&#xff08;属性&#xff09; Props&#xff08;Properties&#xff09;是React组件间传递数据的一种方式。它们是从父组件传递给子组件的只读数据&#xff0c;子组件不能修改这些数据。Props主要用于配置组件&#xff0c;使…

SQL语句补充与示例

在工作中对一些sql感觉陌生&#xff0c;补充一下学习。 SQL语句补充与示例 SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;是一种用于管理和操作关系数据库的标准编程语言。SQL 语句用于执行各种数据库操作&#xff0c;包括查询、更新、插…

记一次老旧项目的整体技术升级

最近给公司采购的老旧的 node8 vue2.6 webpack3 npm 项目做构建优化 背景&#xff1a;整个项目 build 一次 20 min &#xff0c;本地冷启动和热更新也忒慢&#xff0c;依赖 npm i 一下也得装个 20 min 众所周知&#xff0c;Node 版本&#xff0c;依赖包管理工具 和 构建工…