打印1到最大的n位数
2016-05-04 10:07
465 查看
题目:输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1,2,3一直到最大的3位数即999.
第一眼看到这道题是不是觉得很简单?如果你真的觉得很简单,那就掉进这道题的陷阱了。于是你很容易的写出了这样的代码:
初看之下貌似没有问题,但是仔细分析一下这道题,就可以注意到题目中并没有给定n的取值范围。那么问题来了,当然不是挖掘机的问题,而是当输入的n的值很大的时候,大到这个n位数用一个int甚至一个long long来存储都会溢出?也就是说需要考虑大数问题。
那么这道题的解决方法就是在字符串或者数组中模拟一个大数。示例如下:
我的思路是用递归来实现,逻辑简单明了。既然是要打印从1到最大n位数,那么也就相当于答应了n位数的全排列,只是我们再打印的时候,数字前边的0不输出而已。然后实现一个打印函数和一个求全排列的递归,递归退出条件是下标指向‘\0’的那一位。
当然这道题也可以用非递归的方法实现,把求全排列的函数替换为一个每次给字符串对应的数字模拟加1的函数,然后修改一下print_1_to_max_of_n_digits()就可以了。其实也不难,只是代码稍微长一点,这里就不再列出了。但是其中有一个比较重要的问题,每次加1后如何判断是否到了最大的数,每次用strcmp函数比较吗?可是对于长度为n的字符串,它的时间复杂度是O(n)。其实可以注意到只有对999...9加一的时候最高位才会产生进位,我们只需要判断最高位是否产生了进位就可以判断是否到达了最大值,这样的时间复杂度是O(1)的。
第一眼看到这道题是不是觉得很简单?如果你真的觉得很简单,那就掉进这道题的陷阱了。于是你很容易的写出了这样的代码:
void print_1_to_max_of_n_digit(int n) { int max = 1; int i = 0; if (n <= 0) return; for (i = 0; i < n; i++) { max *= 10; } for (i = 1; i < max; i++) { printf("%d\t", i); } }
初看之下貌似没有问题,但是仔细分析一下这道题,就可以注意到题目中并没有给定n的取值范围。那么问题来了,当然不是挖掘机的问题,而是当输入的n的值很大的时候,大到这个n位数用一个int甚至一个long long来存储都会溢出?也就是说需要考虑大数问题。
那么这道题的解决方法就是在字符串或者数组中模拟一个大数。示例如下:
void print_num(char *data, int len) { int i = 0; int flag = 0; while ('0' == data[i]) { i++; } printf("%s\t", data + i); if (0 == flag) { flag = 1; if (0 == strcmp("0", data)) return; } printf("\t"); } void permutation(char *num, int len, int index) //index传进来的下标是当前待设置的下标 { int i = 0; if (len == index) //num[len]已经越界,之前位都已设置,可以打印 { print_num(num, len); return; } for (i = 0; i < 10; i++) { num[index] = i + '0'; permutation(num, len, index + 1); } } void print_1_to_max_of_n_digits(int n) { char *number = (char *)malloc((n + 1) * sizeof(char)); if (n <= 0) return; number = '\0'; permutation(number, n, 0); printf("\n"); free(number); number = NULL; } int main() { print_1_to_max_of_n_digits(3); return 0; }
我的思路是用递归来实现,逻辑简单明了。既然是要打印从1到最大n位数,那么也就相当于答应了n位数的全排列,只是我们再打印的时候,数字前边的0不输出而已。然后实现一个打印函数和一个求全排列的递归,递归退出条件是下标指向‘\0’的那一位。
当然这道题也可以用非递归的方法实现,把求全排列的函数替换为一个每次给字符串对应的数字模拟加1的函数,然后修改一下print_1_to_max_of_n_digits()就可以了。其实也不难,只是代码稍微长一点,这里就不再列出了。但是其中有一个比较重要的问题,每次加1后如何判断是否到了最大的数,每次用strcmp函数比较吗?可是对于长度为n的字符串,它的时间复杂度是O(n)。其实可以注意到只有对999...9加一的时候最高位才会产生进位,我们只需要判断最高位是否产生了进位就可以判断是否到达了最大值,这样的时间复杂度是O(1)的。
相关文章推荐
- 关于GitHub客户端上传代码的使用
- 关于使用v4.app.Fragment,出现“java.lang.VerifyError:”
- OnClickListener接口
- 生成24位字符串ID__IdGenerator.java
- LeMaker Guitar:扩展系统分区
- Spring源码分析——BeanFactory体系之接口详细分析
- Git 与 Github 基础(二)—— Git for Windows
- Coursera 机器学习第9周作业2
- JAVA获取同一路径下所有子类或接口实现类
- localStrorage用法
- 第27章 硬件输入模型和局部输入状态
- RTMP直播应用与延时分析
- 非标准base64编码
- UML类图几种关系的总结
- hibernate 执行原生sql,select返回string,long
- liunx 内存文件 tmpfs
- 数组工具类 - ArrayUtil.java
- mybatis学习(一) 快速入门
- linux系统启动过程
- 广播(BroadcastReceiver)