原创

剑指Offer面试题:11.打印1到最大的n位数

一、题目:打印1到最大的n位数

题目:输入数字n,按顺序打印出从1最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999。

二、不同的解法

2.1 不假思索的解法

  最容易想到的办法是先求出最大的n位数,然后用一个循环从1开始逐个打印:

    static void Print1ToMaxOfNDigitsSimple(int n)
    {
        int number = 1;
        int i = 0;

        while (i < n)
        {
            number = number * 10;
            i++;
        }

        for (i = 1; i < number; i++)
        {
            Console.Write("{0}\t", i);
        }
    }

  初看之下好像没有问题,但是其并没有考虑大数问题,有可能即使用整型(int)或长整型(long)都会溢出。

2.2 字符串模拟运算的解法

  解决这个问题需要表达一个大数。最常用也是最容易的方法是用字符串或者数组表达大数。该算法的步骤如下:

  Step1.把字符串中的每一个数字都初始化为'0';

  Step2.每一次为字符串表示的数字加1,再打印出来;

    static void Print1ToMaxOfNDigits(int n)
    {
        if (n <= 0)
        {
            return;
        }
        // memset(number,'0',n);
        char[] number = new char[n + 1];
        for (int i = 0; i < n; i++)
        {
            number[i] = '0';
        }
        number[n] = '\0';
            
        // Increment实现在表示数字的字符串number上增加1
        while (!Increment(number))
        {
            // PrintNumber负责打印出number
            PrintNumber(number);
        }

        number = null;
    }

    static bool Increment(char[] number)
    {
        bool isOverflow = false;
        int takeOver = 0;
        int length = number.Length - 1;

        for (int i = length - 1; i >= 0; i--)
        {
            int sum = number[i] - '0' + takeOver;
            if (i == length - 1)
            {
                sum++;
            }

            if (sum >= 10)
            {
                if (i == 0)
                {
                    // 标识已经溢出了
                    isOverflow = true;
                }
                else
                {
                    sum -= 10;
                    takeOver = 1;
                    number[i] = (char)('0' + sum);
                }
            }
            else
            {
                number[i] = (char)('0' + sum);
                break;
            }
        }

        return isOverflow;
    }

    static void PrintNumber(char[] number)
    {
        bool isBeginning0 = true;

        for (int i = 0; i < number.Length; i++)
        {
            if (isBeginning0 && number[i] != '0')
            {
                isBeginning0 = false;
            }

            if (!isBeginning0)
            {
                Console.Write("{0}", number[i]);
            }
        }

        Console.Write("\t");
    } 

  这里要注意的是:当数字不够n位的时候,我们在数字的前面补0,打印的时候这些补位的0不应该打印出来。

三、单元测试

3.1 封装测试入口

    static void PrintTest(int n)
    {
        Console.WriteLine("Test for {0} begins:", n);
        Print1ToMaxOfNDigits(n);
        Console.WriteLine("Test for {0} ends.", n);
    }

3.2 测试用例

    static void Main(string[] args)
    {
        PrintTest(1);
        PrintTest(2);
        PrintTest(3);
        PrintTest(0);
        PrintTest(-1);

        Console.ReadKey();
    }

 

正文到此结束
本文目录