面试题12:打印1到最大的n位数##

剑指offer题目12,题目如下

  1. 输入数字n,按顺序打印出1到最大的n位十进制数,比如输入3,则打印出1,2,3一直到最大的三位数999

方法一###

和面试题11《数值的整数次方》类似,乍看觉得都是简单题目,找出最大的n位数,开始逐个打印,写出代码

  1. public static void method_1(int n )
  2. {
  3. int num = 1;
  4. int i = 1;
  5. while(i <= n)
  6. {
  7. num *= 10
  8. i++;
  9. }
  10. for(i = 1;i < num; i++)
  11. System.out.print(i +" ");
  12. }

n的范围小还好,若n的取值很大,即需要考虑大数问题,这就是一个陷阱。正确的做法是使用字符串模拟数字的加法

方法二###

字符串模拟数字加法需要建立一个字符数组,每一个都存储'0'到'9'某一个字符,首先把字符数组中每一位初始化 ‘0’,然后每一次为字符数组做+1操作,最后打印出来。其中的核心操作是

  • 1.为字符数组做+1操作
  • 2.打印数组

    代码如下:
  1. public static void method_2(int n)
  2. {
  3. if(n <= 0)
  4. return;
  5. char num[] = new char[n];
  6. for(int i = 0; i < num.length; i++)
  7. num[i] = '0';
  8. int times = 0; //
  9. while(!increment(num))//数组+1
  10. {
  11. print(num); //输出数组
  12. times ++;
  13. if(time % 10 == 0)//10个换行
  14. {
  15. System.out.println();
  16. times = 0;
  17. }
  18. }
  19. }

剑指offer原书中给出数组+1的方法increment很巧妙,一种方法是字符串数组与最大的N位数99…99匹配,相等则终止递增,但时间复杂度为O(n),另一种方法是在最高位(最左边位)发生了进位,返回True,则就达到了最大的n位数,时间复杂度为O(1),代码如下

  1. ///模拟整数加法
  2. public static boolean increment(char num[])
  3. {
  4. int remider = 0; //进位,5+7 = 12,此时remider=1
  5. for(int i =num.length - 1; i >= 0;i--)
  6. {
  7. int count = num[i] - '0' + remider;
  8. if(i == num.length - 1) //最后一位发生变化
  9. count += 1;
  10. if(count >= 10)
  11. {
  12. if(i == 0)
  13. return true; //最高位发生进位
  14. else
  15. {
  16. count -= 10;
  17. remider = 1;
  18. num[i] = (char) ('0' + count);
  19. }
  20. }
  21. else
  22. {
  23. num[i] = (char) ('0' + count);
  24. break;
  25. }
  26. }
  27. return false;
  28. }

接下开考虑如何打印数字,由于数字由字符数组表示,位数不足n的前面用0补位,比如 当输入的n=3时,数字66的数组表示方式是066,因此在输出的时候遇到前面首数字前面为0的应该跳过去不打印

  1. public static void print(char num[])
  2. {
  3. for(int i = 0;i <= num.length - 1;i++)
  4. {
  5. if(num[i] != '0')
  6. {
  7. for(int j = i;j <= num.length - 1;j++)
  8. {
  9. System.out.print(num[j]);
  10. }
  11. System.out.print(" ");
  12. break;
  13. }
  14. }
  15. }

结果:

方法三###

先给出一个问题,求0~100中数字7出现的个数

可以把数字化成这样00,01,02...98,99,每一数位都是由0到9排列一遍,总共出现100 * 2 = 200个数字,由于0~9这10个数出现的次数相等,则7出现了 200/10 = 20次。

同理,可以在所有的数字前面补0,就会得到n位数字,每一位都是0~9的全排列,只是排在数字前面的0我们不打印出来,由于每一位都是0-9的全排列,可以想到使用递归思路,求数字的全排列Permutation也是类似思想,但有少许区别

  1. // 使用递归
  2. public static void method_3(int n)
  3. {
  4. if(n <= 0)
  5. return;
  6. char num[] = new char[n];
  7. for(int i = 0; i < 10; i++)
  8. {
  9. num[0] = (char) (i + '0');//第0位 全排列0~9
  10. recursive(num,n ,0);
  11. }
  12. }
  13. public static void recursive(char num[],int length ,int index) //index全排列到第几位了
  14. {
  15. if(index == length - 1)
  16. {
  17. System.out.println();
  18. print(num);
  19. return;
  20. }
  21. for(int i = 0; i < 10; i++)
  22. {
  23. num[index + 1] = (char) (i + '0');
  24. recursive(num,length,index + 1);
  25. }
  26. }

总结###

题目简单么?这可要比这些天做的各大公司笔试题算法题目简单太多了,有些公司出的题需要看半天才能表达的意思。这么容易理解的题目如果真是bug free 的做出来还真是有些难度,本节两个关键点:

  • 字符串模拟整数的加法
  • 递归方法全排列数字

《剑指offer》面试题12:打印1到最大的n位数的更多相关文章

  1. 面试题12:打印1到最大的n位数

    // 面试题12_打印1到最大的n位数.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> ...

  2. 剑指offer编程题Java实现——面试题12打印1到最大的n位数

    题目:打印1到最大的n位数 输入数字n,按顺序打印输出从1到最大的n位十进制数,比如输入3,打印从1到999. 这道题考察的地方是如何表示大数问题.由于n是任意大的数组,如果n太大的话n位数就超过了l ...

  3. 剑指Offer:面试题12——打印1到最大的n位数(java实现)

    问题描述: 输入数字n,按顺序打印出从1到最大的n位十进制数,比如输入3,则打印出1,2,3一直到最大的3位数即999. 思路1:最简单的想法就是先找出最大的n位数,然后循环打印即可. public ...

  4. 《剑指offer》面试题12 打印1到最大的n位数 Java版

    书中方法:这道题的一个陷阱在于不能用int或者long去存储你要打印的数,然后用打印函数打印,因为这个数可能会很大.如果加1后超出了最大的n位数,就不打印了.用最高位是否进位判断是否结束,打印的时候注 ...

  5. 剑指offer-面试题12.打印1到最大的n位数

    题目:输入数字n,按照打印出从1最大的n位10进制数.比如3,则 打印出1.2.3一直到最大的3位数即999 1.你觉得如果面试会有这么简单的题,那 只能说明你---太天真. 2.n=3尚可,如果n= ...

  6. 题目12 打印1到最大的n位数

    ///////////////////////////////////////////////////////////////////////////////////// // 2.打印1到最大的n位 ...

  7. 12 打印1到最大的n位数

    输入数字 n,按顺序打印出从 1 最大的 n 位十进制数.比如输入 3,则打印出 1.2.3 一直到最大的 3 位数即 999.由于 n 可能会非常大,因此不能直接用 int 表示数字,而是用 cha ...

  8. 【面试题012】打印1到最大的n位数

    [面试题012]打印1到最大的n位数  大数问题 字符串中的每一个字符都是‘0’到‘9’之间的某一个字符,用来表示数字中的一位,因为数字最大是n位的,因此我们需要一个长度为n+1的字符串,字符串的最后 ...

  9. 剑指offer编程题Java实现——面试题12相关题大数的加法、减法、乘法问题的实现

    用字符串或者数组表示大数是一种很简单有效的表示方式.在打印1到最大的n为数的问题上采用的是使用数组表示大数的方式.在相关题实现任意两个整数的加法.减法.乘法的实现中,采用字符串对大数进行表示,不过在具 ...

随机推荐

  1. onscroll

    var COUNT = 0, demo = document.getElementById('demo'); function testFn() {demo.innerHTML += 'testFN ...

  2. ssh 整合

    1. 加入 Spring 1). 加入 jar 包 2). 配置 web.xml 文件 3). 加入 Spring 的配置文件. 2. 加入 Hibernate 1). 同时建立持久化类, 和其对应的 ...

  3. VS2012+LUA环境搭建

    1 .启动VS2012,选择C++下的"win32"项目类型中的"Win2控制台应用程序" 2.工具——选项——项目和解决方案——VC++目录——可执行程序(C ...

  4. iOS程序启动过程

    First, the function creates the main application object (step 3 in the flowchart). If you specify ni ...

  5. SQL数据库,使用事务执行增删改操作,给自己一个后悔的机会

    内容并不复杂,使用起来也比较简单. 主要使用以下3条SQL语句: 开始事物:BEGIN TRAN(全拼 TRANSACTION 亦可)提交事物:COMMIT TRAN回滚事务:ROLLBACK TRA ...

  6. java1234初学maven

    第一讲: maven maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. maven安装与下载: .确定jdk已经安装并且配置 .安装mav ...

  7. python简单文件操作

    写软件著作申请,需要将所有源代码代码贴入一个word中,在源代码前后要添加一些标记,如下: //////////////////////////// //filename1 ///////////// ...

  8. mseed2sac的安装和使用

    由于使用rdseed提取mseed文件到SAC文件会遇到一个问题就是: 同时需要dataless文件: 因此如果下载的数据中恰巧没有dataless文件,则需要用另外一种方式:mseed2sac 现在 ...

  9. MySQL 通过semi join 优化子查询

    半连接是MySQL 5.6.5引入的,多在子查询exists中使用,对外部row source的每个键值,查找到内部row source匹配的第一个键值后就返回,如果找到就不用再查找内部row sou ...

  10. jQuery专题

    jQuery概述 ·为了简化JavaScript的开发,一些JavaScript库诞生了.JavaScript库封装了很多预定义的对象和实用函数.能帮助使用者建立有高难度交互的Web2.0特性的富客户 ...