Leetcode17. 电话号码的字母组合:递归树深度遍历(C++vector和string的小练习)

简介: Leetcode17. 电话号码的字母组合:递归树深度遍历(C++vector和string的小练习)

目录

一.Leetcode17:电话号码的字母组合

1.问题描述

2.问题分析与求解

3.递归函数的建立

4.题解代码

二.leetcode118. 杨辉三角(二维vector的运用)

一.Leetcode17:电话号码的字母组合
1.问题描述

  1. 电话号码的字母组合 - 力扣(Leetcode)

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

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 3:

输入:digits = "2"
输出:["a","b","c"]
注意:字符串digits的长度为0到4闭区间范围内。

C++题解接口:

class Solution
{

public:

vector<string> letterCombinations(string digits) 
{

}

};
2.问题分析与求解
以digits="23"为例建立字符排列组合的树形图:

根据三叉树的结构我们尝试建立递归(树的每一个节点就是一次函数调用):

三叉树的每层的层数我们记为level(level的最大值由digits字符串的有效字符个数决定)

为了确定每一层树节点中的phonestr字符串我们需要建立一个简单的映射表strmap:
string strmap[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
映射表strmap是一个由10个string对象构成的数组:

每个string对象中存储的字符串与其下标的映射关系刚好与题目中字符与按键的映射关系一致。

3.递归函数的建立
建立递归函数首部:

void _deepSearch (const string&digits , vector&answer , int level, string&temstr)
digits是题目给出的按键字符串,answer是用于存储各个可能字母组合的由string对象构成的vector,level用于控制递归的深度(层数),当level等于digits字符串的长度时停止递归,temstr是存储临时字母组合的string对象,当递归达到最深层时,就将temstr对象存入answer中。

递归函数中控制递归条件的语句:

    if(level == digits.size())
    {
        answer.push_back(temstr);  递归到最深层,将temstr存入answer中
        return ;
    }

每一次函数调用中确定phonestr字符串(记录了每层递归中参与组合的字符)的语句:

string phonestr(strmap[digits[level]-'0']);
多叉树向更深层次展开的语句:

    for (int i = 0; i < phonestr.size(); i++)
    {
        temstr.push_back(phonestr[i]); 将字符尾插到字符组合中
        _deepSearch(digits, answer, level + 1, temstr);
        temstr.pop_back();             完成递归调用后要将该层中插入的字符删掉完成回溯
    }

完整的递归函数代码:

void _deepSearch(const string& digits, vector& answer, int level, string& temstr)
{

    if (level == digits.size())
    {
        answer.push_back(temstr);
        return;
    }
    string phonestr(strmap[digits[level] - '0']);
    for (int i = 0; i < phonestr.size(); i++)
    {
        temstr.push_back(phonestr[i]);
        _deepSearch(digits, answer, level + 1, temstr);
        temstr.pop_back();
    }

}

递归树遍历顺序:

4.题解代码
class Solution
{
private:

string strmap[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
void _deepSearch (const string&digits , vector<string>&answer , int level, string&temstr)
{
    if(level == digits.size())
    {
        answer.push_back(temstr); //将可能的字母组合存入answer容器中
        return ;
    }
    string phonestr(strmap[digits[level]-'0']);
    for(int i =0; i<phonestr.size();i++)
    {
        temstr.push_back(phonestr[i]);
        _deepSearch(digits,answer,level+1,temstr);
        temstr.pop_back();      //尾插字符后再尾删字符完成字符串回溯
    }
}

public:

vector<string> letterCombinations(string digits) 
{
    vector<string> answer;
    if(digits.empty())          //检查digits是否为空字符串
    {
        return answer;
    }
    string temstr;              //用于存储每个'树叶'临时得到的字母组合
    _deepSearch(digits,answer,0,temstr);
    return answer;
}

};

注意:

题解接口函数中注意检查digits是否为空字符串

二.leetcode118. 杨辉三角(二维vector的运用)

  1. 杨辉三角 - 力扣(Leetcode)

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。

示例 :

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]
C语言题解接口:

int generate(int numRows, int* returnSize, int returnColumnSizes)
{

}
本题如果使用C语言求解需要在堆区上模拟出一个numRows行numRows列的二维数组。

int parr = (int )malloc(sizeof(int)numRows);
int i =0;
for(i=0;i<numRows;i++)
{

parr[i]= (int *)malloc(sizeof(int)*(i+1));

}
图解堆区上的二维数组:

C语言中堆区上的动态二维数组有如下几个不方便使用的小缺点:

在堆区上多次用malloc申请随机地址的空间,会使堆区上的内存碎片增多,内存利用率降低
多个堆区上的内存区块释放时很麻烦,让内存管理变得繁琐,容易造成内存泄漏
多级指针和动态的指针数组未经封装,会让代码的可阅读性和可维护性降低
本题使用C语言写起来比较恶心,用C++的二维vector写起来会舒服很多

C++题解接口:

class Solution
{
public:

vector<vector<int>> generate(int numRows) 
{
    
}

};
题解代码:

class Solution
{
public:

vector<vector<int>> generate(int numRows) 
{
    vector<vector<int>> answer(numRows);
    int i =0;
    int j=0;
    for(i=0;i<numRows;i++)
    {
        answer[i].resize(i+1);
        answer[i][0]=1;
        answer[i][i]=1;
    }
    for(i=2;i<numRows;i++)
    {
        for(j=1;j<i;j++)
        {
            answer[i][j]=answer[i-1][j]+answer[i-1][j-1];                   
        }
    }
    return answer;
}

};

vector的带参构造函数其中一个重载形式:
explicit vector (size_type n, const value_type& val = value_type(),

                          const allocator_type& alloc = allocator_type());





可见需要用到动态二维数组时,vector使用起来会非常方便

相关文章
|
存储 安全 C语言
C++ String揭秘:写高效代码的关键
在C++编程中,字符串操作是不可避免的一部分。从简单的字符串拼接到复杂的文本处理,C++的string类为开发者提供了一种更高效、灵活且安全的方式来管理和操作字符串。本文将从基础操作入手,逐步揭开C++ string类的奥秘,帮助你深入理解其内部机制,并学会如何在实际开发中充分发挥其性能和优势。
|
12月前
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
295 17
|
11月前
|
对象存储 C++ 容器
c++的string一键介绍
这篇文章旨在帮助读者回忆如何使用string,并提醒注意事项。它不是一篇详细的功能介绍,而是一篇润色文章。先展示重载函数,如果该函数一笔不可带过,就先展示英文原档(附带翻译),最后展示代码实现与举例可以直接去看英文文档,也可以看本篇文章,但是更建议去看英文原档。那么废话少说直接开始进行挨个介绍。
211 3
|
12月前
|
存储 算法 Go
【LeetCode 热题100】17:电话号码的字母组合(详细解析)(Go语言版)
LeetCode 17题解题思路采用回溯算法,通过递归构建所有可能的组合。关键点包括:每位数字对应多个字母,依次尝试;递归构建下一个字符;递归出口为组合长度等于输入数字长度。Go语言实现中,使用map存储数字到字母的映射,通过回溯函数递归生成组合。时间复杂度为O(3^n * 4^m),空间复杂度为O(n)。类似题目包括括号生成、组合、全排列等。掌握回溯法的核心思想,能够解决多种排列组合问题。
497 11
|
存储 算法 数据可视化
【二叉树遍历入门:从中序遍历到层序与右视图】【LeetCode 热题100】94:二叉树的中序遍历、102:二叉树的层序遍历、199:二叉树的右视图(详细解析)(Go语言版)
本文详细解析了二叉树的三种经典遍历方式:中序遍历(94题)、层序遍历(102题)和右视图(199题)。通过递归与迭代实现中序遍历,深入理解深度优先搜索(DFS);借助队列完成层序遍历和右视图,掌握广度优先搜索(BFS)。文章对比DFS与BFS的思维方式,总结不同遍历的应用场景,为后续构造树结构奠定基础。
608 10
|
11月前
|
Java C++
力扣第一道困难题《3. 无重复字符的最长子串》,c++
首先我们看到这个题是肯定有一种暴力的硬解思路的,那就是将两个vector直接链接起来,然后再排序后,直接返回中间值,这个方法实现起来还是非常容易的,
401 0
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
575 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
519 12
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
270 10