Leetcode17. Alphabet combinations of phone numbers: recursive tree depth traversal (small exercises for C++vector and string)

Table of contents

1. Leetcode17: Alphabet combinations of phone numbers

1. Problem description

2. Problem analysis and solution

3. Establishment of recursive function

4. Solution code

2. leetcode118. Yang Hui triangle (the application of two-dimensional vector)


1. Leetcode17: Alphabet combinations of phone numbers

1. Problem description

17. Alphabet combinations for phone numbers - Leetcode

Given a  string containing only numbers 2-9 , return all possible combinations of letters it can represent. The mapping of numbers to letters is given as follows (same as for phone keys). Note that 1 does not correspond to any letter .

 

Example 1:

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

Example 3:

Input: digits = "2" 
Output: ["a", "b", "c"]

Note: The length of the string digits is in the range of 0 to 4 closed intervals .

C++ solution interface:

class Solution 
{

public:
    vector<string> letterCombinations(string digits) 
    {

    }
};

2. Problem analysis and solution

Take digits="23" as an example to create a tree diagram of character arrangement and combination :

According to the structure of the ternary tree, we try to build recursion ( each node of the tree is a function call ):

  • The number of layers of each layer of the ternary tree is recorded as level (the maximum value of level is determined by the number of valid characters in the digits string)
  • In order to determine the phonestr string in each tree node we need to create a simple mapping table strmap:
    string strmap[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

    The mapping table strmap is an array of 10 string objects:

    The mapping relationship between the character string and its subscript stored in each string object is exactly the same as the mapping relationship between characters and keys in the title . 

3. Establishment of recursive function

  • Create a recursive function header:

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

    digits is the key string given in the title, answer is a vector composed of string objects used to store each possible letter combination, level is used to control the depth (number of layers) of recursion , and stop recursion when level is equal to the length of the digits string , temstr is a string object that stores a temporary combination of letters. When the recursion reaches the deepest level, the temstr object is stored in answer .

  • Statements in recursive functions that control recursive conditions:

            if(level == digits.size())
            {
                answer.push_back(temstr);  递归到最深层,将temstr存入answer中
                return ;
            }
  • The statement for determining the phonestr string (recording the characters participating in the combination in each layer of recursion) in each function call :

    string phonestr(strmap[digits[level]-'0']);
  • The statement that the multi-fork tree expands to a deeper level:

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

     void _deepSearch(const string& digits, vector<string>& 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();
            }
     }

    Recursive tree traversal order:

4. Solution code

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;
    }
};

 Notice:

  • Pay attention to check whether digits is an empty string in the solution interface function

2. leetcode118. Yang Hui triangle (the application of two-dimensional vector)

118. Yang Hui Triangle - Leetcode

Given a non-negative integer  numRows, generate antecedents of the Yanghui Triangle  numRows .

Example :

Input: numRows = 5 
Output: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

C language solution interface:

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

}

If you use C language to solve this problem, you need to simulate a two-dimensional array with numRows rows and numRows columns on the heap .

int** parr = (int **)malloc(sizeof(int*)*numRows);
int i =0;
for(i=0;i<numRows;i++)
{
    parr[i]= (int *)malloc(sizeof(int)*(i+1));
}

Plot a 2D array on the heap:

The dynamic two-dimensional array on the heap in C language has the following disadvantages that are inconvenient to use:

  1. Using malloc multiple times to apply for random address space on the heap area will increase memory fragmentation on the heap area and reduce memory utilization.
  2. It is very troublesome to release memory blocks on multiple heaps, which makes memory management cumbersome and easily causes memory leaks
  3. Multi-level pointers and dynamic pointer arrays are not encapsulated, which will reduce the readability and maintainability of the code

This question is disgusting to write in C language, but it will be much more comfortable to write in C++ two-dimensional vector

C++ solution interface:

class Solution 
{
public:
    vector<vector<int>> generate(int numRows) 
    {
        
    }
};

Solution code:

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;
    }
};
  •  One of the overloaded forms of vector's parameterized constructor:
    explicit vector (size_type n, const value_type& val = value_type(),
                                  const allocator_type& alloc = allocator_type());

  • It can be seen that when a dynamic two-dimensional array is needed, vector will be very convenient to use

Guess you like

Origin blog.csdn.net/weixin_73470348/article/details/128886436