숫자 n을 입력하고 1부터 가장 큰 n 자리 십진수까지 순서대로 인쇄합니다. 예를 들어, 3을 입력하면 1, 2, 3이 최대 3 자리 999까지 인쇄됩니다.
예 1 :
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]
설명 : n을 양의 정수로
인쇄하는 대신 정수 목록 반환을 사용
합니다.
대량 인쇄 솔루션 :
사실,이 질문의 주요 테스트 포인트는 많은 수가 범위를 벗어날 때 인쇄하는 것입니다. 다음 세 가지 문제를 해결해야합니다.
1. 큰 수를 나타내는 변수 유형 :
short / int / long… 어떤 변수 유형이든 상관없이 숫자의 값 범위는 제한됩니다. 따라서 큰 수의 표현은 문자열 유형이어야합니다.
2. 숫자의 문자열 세트를 생성합니다.
int 타입을 사용하면 라운드마다 +1 씩 다음 숫자를 생성 할 수 있으며이 방법은 String 타입에 적용 할 수 없습니다. 또한 문자열 유형 번호의 캐리 작업 효율이 낮습니다. 예를 들어 "9999"에서 "10000"까지 1 자리에서 천 자리로 순환해야하며 캐리는 4 회입니다.
관찰 결과 생성 된 목록은 실제로 n 비트 0-9의 전체 배열이므로 캐리 작업을 피할 수 있으며 숫자의 문자열 목록을 재귀 적으로 생성 할 수 있습니다.
3. 모든 순열을 재귀 적으로 생성합니다.
분할 및 정복 알고리즘의 아이디어를 바탕으로 먼저 높은 자리를 고정하고 낮은 자리로 재귀합니다 .1 자리가 고정되면 숫자 문자열을 추가합니다. 예를 들어, n = 2 (숫자 범위 1-99) 인 경우 고정 십 자리는 0-9이고, 순서대로 재귀를 켜고, 한 자리 0-9를 수정하고, 재귀를 종료하고, 숫자 문자열을 추가합니다.
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;
}
};