[Leetcode 60 days with brush] day25 backtracking algorithm - 216. Combination sum III, 17. Letter combination of phone number

 


  topic:

216. Combined Sum III

n Find the combination of all numbers whose  sum is sum  k , and satisfy the following conditions:

  • Only use numbers 1 to 9
  • Use each number  at most once 

Returns  a list of all possible valid combinations  . The list cannot contain the same combination twice, and the combinations may be returned in any order.

Example 1:

Input:  k = 3, n = 7
 Output: [[1,2,4]]
 Explanation:
1 + 2 + 4 = 7
No other combinations match.

Example 2:

Input:  k = 3, n = 9
 Output: [[1,2,6], [1,3,5], [2,3,4]]
 Explanation:
 1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
No other combinations match.

Example 3:

Input: k = 4, n = 1
 Output: []
 Explanation: No valid combination exists.
Using 4 different numbers in the range [1,9], the smallest sum we can get is 1+2+3+4 = 10, since 10 > 1, there is no valid combination.

hint:

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

Thinking process and knowledge points: 

  • Determine recursive function parameters

Like 77. Combination (opens new window) , the one-dimensional array path is still required to store the qualified results, and the two-dimensional array result is used to store the result set.

Here I still define path and result as global variables.

As for why it is named path? From the above tree structure, it can be seen that the result is actually a path from the root node to the leaf node.

Next, the following parameters are required:

  • targetSum (int) target sum, which is n in the title.
  • k (int) is the set of k numbers required in the title.
  • sum (int) is the sum of the collected elements, that is, the sum of the elements in the path.
  • startIndex (int) is the starting position of the next for loop search.

So the code is as follows:

vector<vector<int>> result;
vector<int> path;
void backtracking(int targetSum, int k, int sum, int startIndex)

In fact, the sum parameter can also be omitted here. Each time the targetSum is subtracted from the selected element value, and then it is judged that if the targetSum is 0, it means that the result that meets the conditions has been collected. For the sake of intuitive understanding, I still add a sum parameter.

It should also be emphasized that it is difficult to determine the parameters of the recursive function in the backtracking method at one time. Generally, the logic is written first, what parameters are needed, and what parameters to fill in.

  • Determine the termination condition

When will it end?

As mentioned above, k actually limits the depth of the tree, because only k elements are taken, and it is meaningless for the tree to go deeper.

So if path.size() is equal to k, terminate.

If the elements collected in the path at this time are the same as (sum) and targetSum (that is, the n described in the title), use result to collect the current result.

So the termination code is as follows:

if (path.size() == k) {
    if (sum == targetSum) result.push_back(path);
    return; // 如果path.size() == k 但sum != targetSum 直接返回
}
  • single layer search process

The processing process is that path collects the elements selected each time, which is equivalent to the edges in the tree structure, and sum counts the sum of the elements in the path.

code show as below:

for (int i = startIndex; i <= 9; i++) {
    sum += i;
    path.push_back(i);
    backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
    sum -= i; // 回溯
    path.pop_back(); // 回溯
}

Don't forget that there is a one-to-one correspondence between the processing process and the backtracking process. If there is an increase in processing, there will be a subtraction in backtracking!


  answer:

class Solution {
private:
    vector<vector<int>> result; // 存放结果集
    vector<int> path; // 符合条件的结果
    // targetSum:目标和,也就是题目中的n。
    // k:题目中要求k个数的集合。
    // sum:已经收集的元素的总和,也就是path里元素的总和。
    // startIndex:下一层for循环搜索的起始位置。
    void backtracking(int targetSum, int k, int sum, int startIndex) {
        if (path.size() == k) {
            if (sum == targetSum) result.push_back(path);
            return; // 如果path.size() == k 但sum != targetSum 直接返回
        }
        for (int i = startIndex; i <= 9; i++) {
            sum += i; // 处理
            path.push_back(i); // 处理
            backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
            sum -= i; // 回溯
            path.pop_back(); // 回溯
        }
    }

public:
    vector<vector<int>> combinationSum3(int k, int n) {
        result.clear(); // 可以不加
        path.clear();   // 可以不加
        backtracking(n, k, 0, 1);
        return result;
    }
};

  topic:

17. Alphabet combinations for phone numbers

Given a  2-9 string containing only numbers, return all possible combinations of letters it can represent. Answers can be returned in  any order  .

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 2:

Input: digits = ""
 Output: []

Example 3:

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

hint:

  • 0 <= digits.length <= 4
  • digits[i] is  ['2', '9'] a number in the range.

 Thinking process and knowledge points: 

After understanding this question, the following three questions should be solved:

  1. How Numbers and Letters Map
  2. Two for loops for two letters, three for loops for three characters, and so on, and then I found that the code couldn’t be written at all
  3. Enter 1 * # button and other abnormal conditions

First, a string s is needed to collect the results of the leaf nodes, and then a string array result is used to save them. I still define these two variables as global.

Look at the parameters again. The parameter specification is the string digits given in the title, and then there is another parameter that is the int type index.

The termination condition is if the index is equal to the number of digits entered (digits.size) (the original index is used to traverse digits).

Then collect the results and end the recursion at this level.


 answer:

class Solution {
private:
    const string letterMap[10] = {
        "", // 0
        "", // 1
        "abc", // 2
        "def", // 3
        "ghi", // 4
        "jkl", // 5
        "mno", // 6
        "pqrs", // 7
        "tuv", // 8
        "wxyz", // 9
    };
public:
    vector<string> result;
    string s;
    void backtracking(const string& digits, int index) {
        if (index == digits.size()) {
            result.push_back(s);
            return;
        }
        int digit = digits[index] - '0';        // 将index指向的数字转为int
        string letters = letterMap[digit];      // 取数字对应的字符集
        for (int i = 0; i < letters.size(); i++) {
            s.push_back(letters[i]);            // 处理
            backtracking(digits, index + 1);    // 递归,注意index+1,一下层要处理下一个数字了
            s.pop_back();                       // 回溯
        }
    }
    vector<string> letterCombinations(string digits) {
        s.clear();
        result.clear();
        if (digits.size() == 0) {
            return result;
        }
        backtracking(digits, 0);
        return result;
    }
};

Welcome to like, bookmark, comment, your encouragement is the biggest motivation for my creation! (๑╹◡╹)ノ"""

Copyright statement: This article is an original article of CSDN blogger "Dumengjiu", which follows the CC 4.0 BY-SA copyright agreement. For reprinting, please attach the original source link and this statement.
Original link: Dumengjiu's blog_CSDN blog-csdn domain blogger

Guess you like

Origin blog.csdn.net/weixin_53310927/article/details/131355950