剑指 Offer 17. 打印从1到最大的n位数
思路
(1) 不考虑n很大的情况
1 class Solution { 2 public: 3 vector<int> printNumbers(int n) { 4 vector<int> res; 5 int m = 1; 6 for(int i = 0; i < n; ++i) 7 m = m*10; 8 9 for(int i = 1; i < m; ++i) 10 res.push_back(i); 11 12 return res; 13 } 14 };
(2) 考虑n很大的情况
方法一:使用字符串模拟数字的加法
1 bool increment(string& num); 2 void printNumber(const string& num); 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 string maxNum(n, '9'); 9 string num(n, '0'); 10 while(!increment(num)) { //使用了O(1)时间判断是否已经自增到了最大值 11 printNumber(num); 12 printf("\t"); 13 } 14 15 return 0; 16 } 17 18 //自增1 19 //使用了O(1)时间判断是否已经自增到了最大值 20 bool increment(string& num) { 21 bool isHighestBitCarry = false; //最高位是否进位 22 int numLen = num.length(); 23 int carry = 0; //进位 24 25 for(int i = numLen-1; i >= 0; --i) { 26 int x = num[i] -'0' + carry; 27 carry = 0; 28 if(i == numLen-1) { 29 x += 1; 30 } 31 32 if(x >= 10) { 33 carry++; //产生进位 34 if(i == 0) 35 isHighestBitCarry = true; 36 x -= 10; 37 } 38 39 num[i] = '0' + x; 40 } 41 42 return isHighestBitCarry; 43 } 44 45 46 //打印的时候消去前置0 47 void printNumber(const string& num) { 48 bool isBeginWith0 = true; 49 for(int i = 0; i < num.length(); ++i) { 50 if(num[i] != '0') 51 isBeginWith0 = false; 52 if(!isBeginWith0) 53 printf("%c", num[i]); 54 } 55 }
方法二:把问题转换成数字排列的解法
1 void printNumber(const string& num); 2 void dfs(string& num, int n, int step); 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 string num(n, '0'); 9 dfs(num, n, 0); 10 11 return 0; 12 } 13 14 //递归打印数字排列 15 void dfs(string& num, int n, int step) { 16 if(step == n) { 17 printNumber(num); 18 printf("\t"); 19 return; 20 } 21 22 for(int i = 0; i < 10; ++i) { 23 num[step] = '0' + i; 24 dfs(num, n, step+1); 25 } 26 } 27 28 //打印的时候消去前置0 29 void printNumber(const string& num) { 30 bool isBeginWith0 = true; 31 for(int i = 0; i < num.length(); ++i) { 32 if(num[i] != '0') 33 isBeginWith0 = false; 34 if(!isBeginWith0) 35 printf("%c", num[i]); 36 } 37 }
复杂度分析
参考
《剑指offer(第2版)》- 面试题17:打印从1到最大的n位数