Sword refers to Offer 17. Print from 1 to the largest n digits (C++) Recursion + DFS

Enter the number n, and print out in order from 1 to the largest n-digit decimal number. For example, input 3, then 1, 2, 3 will be printed out up to the maximum 3 digits 999.

Example 1:

输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]

Description:
Use returning a list of integers instead of printing
n as a positive integer

Large number printing solution:

In fact, the main test point of this question is printing when large numbers are out of bounds. The following three problems need to be solved:

1. Variable types that represent large numbers:

No matter it is short / int / long… any variable type, the value range of the number is limited. Therefore, the representation of large numbers should be of String type.
2. Generate a string set of numbers:

When using the int type, the next number can be generated by +1 each round, and this method cannot be applied to the String type. In addition, the carry operation efficiency of String type numbers is low. For example, "9999" to "10000" need to cycle from the ones digit to the thousands digit, and the carry is 4 times.
Observation shows that the generated list is actually a full array of n bits 0-9, so the carry operation can be avoided and a String list of numbers can be generated recursively.
3. Recursively generate all permutations:

Based on the idea of ​​divide and conquer algorithm, first fix the high digit and recurse to the low digit. When the ones digit is fixed, add a string of numbers. For example, when n = 2 (number range 1-99), the fixed tens digit is 0-9, turn on the recursion in sequence, fix the one digit 0-9, terminate the recursion and add a number string.

Insert picture description here
Insert picture description here
Insert picture description here

class Solution {
    
    
private:
	//下面三行定义变量
	vector<int> res; 
	int nine = 0, count = 0, start, n;
	vector<char> num, loop = {
    
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
	void dfs(int x) {
    
    
        if(x == n) {
    
    //x == n才是表示完全添加索引为n-1的字符
			string s,sub;//定义字符串变量
			s.insert(s.begin()/*插入的位置*/, num.begin()/*插入对象的开始位置*/, num.end()/*插入对象的结束位置*/);
			//上一行vector<char> 转string
			sub=s.substr(start);//s的start位开始截取一段字符串
            if(!(sub=="0")) res[count++] = stoi(sub);//剔除“0”
            if(n - start == nine) start--;//设数字各位中 9 的数量为 nine ,所有位都为 9 的判断条件可用;
			//start--,表示扩增一位数,例如;“999”,start--变成n-4,为“1000”留位置
            return;//return;的作用相当于continue;用于中断此轮循环的作用,
        }
        for(char i : loop) {
    
    
            if(i == '9') nine++;//统计“9”的个数
            num[x] = i;//字符拼接到数组里面
            dfs(x + 1);//数字的下一位
        }
        nine--;//并在回溯前恢复 nine = nine - 1 。
    }
public:
    vector<int> printNumbers(int n) {
    
    
		this->n = n;
		res.resize(pow(10, n) - 1);//res数组的内存分配
		num.resize(n);//数组元素的位数内存分配
		start = n-1;//其实就是截取字符串的最后一位
		dfs(0);
		return res;
	}
};

Complexity analysis:

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_30457077/article/details/114754397