打印从1到最大的n位数
关键词:数学、递归、字符串、大数
题目描述
输入数字 n
,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例 1:
1 2
| 输入: n = 1 输出: [1,2,3,4,5,6,7,8,9]
|
思路
思路一:
针对本题的常规思路,利用pow函数,秒解
思路二:
如果出现大数,则需要借助字符串进行求解。
有大数解法 char版和string版。
思路三:
递归求解
打印的其实是各个位上0-9的一个排列,所以可以采用递归的思想,一次给每个位赋值,赋值到个位(也就是第n位)时将其进行保存。
代码
思路一:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Solution { public: vector<int> printNumbers(int n) { vector<int> res; if (n == 0) return res; for (int i=1,max=pow(10,n);i<max;i++) { res.push_back(i); } return res; } };
|
思路二 char:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| #include <iostream> #include <vector> #include <memory.h>
using namespace std;
vector<int> res; bool Increment(char* number) { bool isOverflow = false; int nTakeOver = 0; int nLength = strlen(number); for (int i = nLength - 1; i >= 0; i--) { int nSum = number[i] - '0' + nTakeOver; if (i == nLength - 1) { nSum++; } if (nSum >= 10) { if (i == 0) { isOverflow = true; } else { nTakeOver = 1; number[i] = nSum - 10 + '0'; } } else { number[i] = nSum + '0'; break; } } return isOverflow; } void PrintNumber(char* number)
{ string s = ""; bool isBegin0 = true; while (*number != '\0') { if (isBegin0 && *number != '0') isBegin0 = false; if (!isBegin0) { s += *number; } number++; } int num = stoi(s); res.push_back(num); } vector<int> printNumbers(int n) { if (n <= 0) return res; char* number = new char[n + 1]; memset(number, '0', n); number[n] = '\0'; while (!Increment(number)) { PrintNumber(number); } delete[]number; return res; }
int main() { vector<int> vec = printNumbers(3); for(int a : vec) { cout << a << " "; } cout << endl; return 0; }
|
思路二 string:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| #include <iostream> #include <vector>
using namespace std;
vector<int> res;
bool Increment(string& number) { bool isOverflow = false; int nTakeOver = 0; int nLength = number.size(); for (int i = nLength - 1; i >= 0; i--) { int nSum = number[i] - '0' + nTakeOver; if (i == nLength - 1) { nSum++; } if (nSum >= 10) { if (i == 0) { isOverflow = true; } else { nTakeOver = 1; number[i] = nSum - 10 + '0'; } } else { number[i] = nSum + '0'; break; } } return isOverflow; } void saveNumber(string number)
{ string s = ""; bool isBegin0 = true; string::iterator it = number.begin(); while (it != number.end()) { if (isBegin0 && *it != '0') isBegin0 = false; if (!isBegin0) { s += *it; } it++; } int num = stoi(s); res.push_back(num); } vector<int> printNumbers(int n) { if (n <= 0) return res; string number(n, '0'); while (!Increment(number)) { saveNumber(number); } return res; }
int main() { vector<int> vec = printNumbers(3); for(int i : vec){ cout << i << " "; } cout << endl; return 0; }
|
思路三:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| #include <iostream> #include <vector> #include <string>
using namespace std;
vector<int> res;
void saveNumber(string number) { bool isBegin0 = true; string tempStr = ""; string::iterator it = number.begin(); while(it != number.end()) { if(isBegin0 && *it != '\0') isBegin0 = false; if(!isBegin0){ tempStr += *it; } it++; } if(tempStr != ""){ int tempNum = stoi(tempStr); res.push_back(tempNum); } }
void permutationNumbers(string& number, int length, int index) { if(index == length){ saveNumber(number); return; } else { for(int i = 0; i <= 9; i++) { number[index] = '0' + i; permutationNumbers(number, length, index + 1); } } }
vector<int> printNumbers(int n) { if(n <= 0) return res; string number(n, '0'); for(int i = 0; i <= 9; i++){ number[0] = i + '0'; permutationNumbers(number, n, 1); } return res; }
int main() { vector<int> tst = printNumbers(3); for(int i : tst){ cout << i << " "; } cout<<endl; return 0; }
|
知识点
pow函数的使用
pow(base, exp)求解base的exp次方,包含于cmath头文件。
大数问题一般会考虑使用char或者string进行求解,通过设置越界标志和进位标志来辅助运算。
stoi函数的使用
stoi( const std::string& str, std::size_t* pos = 0, int base = 10 );
舍弃所有空白符(以调用 isspace() 鉴别),直到找到首个非空白符,然后取尽可能多的字符组成底 n (其中 n=base )的整数表示,并将它们转换成一个整数值。合法的整数值由下列部分组成:
- (可选)正或负号
- (可选)指示八进制底的前缀( 0 )(仅当底为 8 或 0 时应用)
- (可选)指示十六进制底的前缀( 0x 或 0X )(仅当底为 16 或 0 时应用)
- 一个数字序列
底的合法集是 {0,2,3,…,36} 。合法数字集对于底 2 整数是 {0,1},对于底3整数是 {0,1,2} ,以此类推。对于大于 10 的底,合法数字包含字母字符,从对于底 11 整数的 Aa 到对于底36整数的 Zz 。忽略字符大小写。