• 剑指offer--面试题12


    题目:打印从1~最大的n位数

    分析:知道陷阱在哪,即n很大时若用通常的int,long会溢出;想到用字符串解决,这涉及到字符转数字及反过来。

      刚开始纠结于字符串怎么加1,想了片刻,觉得应该取出最后一位上的字符,转成数字+1再转成字符,但这就出现个问题:'9'加1后得到'10',这会产生进位。。。

      到这思维就乱了。。。1、不断向前进位怎么解决?2、怎么判断到达最大值?

    在看过作者的代码后才豁然开朗。。。,解决方案:1、将进位与不进位分开,并且进位时设定nTakeOver用于下一字符的加,该过程用循环完成;2、同样判断最大值时,若第一位的数值=10了,那肯定已经到达最大值了

    结合参考代码,自己所写代码如下:

    #include "stdafx.h"
    #include <iostream>
    
    using namespace std;
    
    void PrintNumber(char* number);  //打印数字
    bool Increment(char* number,int length);  //加1
    
    // ====================方法一====================
    void Print1ToMaxOfNDigits_1(int n)
    {
        if(n <= 0)
            return;  //错误处理
     
        char *number = new char[n + 1];
        memset(number, '0', n);   //memset()函数设置number的前n位为字符‘0’:memset(number,'0',n);  该函数位于<memory>
        number[n] = '';         //注意字符串以‘/0’结尾!!!
     
        while(!Increment(number,n))
        {
            PrintNumber(number);
        }   //加1成功则打印
     
        delete [] number;
    }
    
    
    
    //实现加1操作
    //一直到某位上的数值不超过9,终止循环
    //利用循环向前进位
    bool Increment(char* number, int length)
    {
        bool isOverFlow = false;
        int nTakeOver = 0;
        for(int i=length-1; i>=0; i--)
        {
            //加1,要考虑之前的进位nTakeOver
            int num_value = number[i] - '0' + nTakeOver;
            if(i == length-1)
                num_value += 1;
            if(num_value <= 9)
            {
                number[i] = num_value + '0';
                break;
            }
            else
            {
                //达到最大n位数后终止
                if(i == 0)
                    isOverFlow = true;
                else
                {
                    nTakeOver = 1;
                    number[i] = num_value - 10 + '0';
                }
            }
        }
    
        return isOverFlow;
    }
    
    //打印字符串表示的数字
    void PrintNumber(char* number)
    {
        while(*number != '')
        {
            if(*number == '0')
                number++;
            else
            {
                cout<<number<<'	';
                break;
            }
        }
    }
    
    // ====================测试代码====================
    void Test(int n)
    {
        printf("Test for %d begins:
    ", n);
    
        Print1ToMaxOfNDigits_1(n);
    
        printf("Test for %d ends.
    ", n);
    }
    
    int main()
    {
        Test(1);
        Test(2);
        Test(3);
        Test(0);
        Test(-1);
    
        return 0;
    }

    说明:只是在PrintNumber子函数上做了些改进。

    另一种思路:因为每位为0~9,共n位,所以数字个数=10^n-1,因此相当于全排列的方法,而全排列可用递归实现

    这种方法由于涉及到递归,所以自己很难想到,即便想到也很难写出来。。。

    参考代码如下:

    // ====================方法二====================
    void Print1ToMaxOfNDigits_2(int n)
    {
        if(n <= 0)
            return;
     
        char* number = new char[n + 1];
        number[n] = '';
     
        for(int i = 0; i < 10; ++i)
        {
            number[0] = i + '0';
            Print1ToMaxOfNDigitsRecursively(number, n, 0);
        }
     
        delete[] number;
    }
     
    void Print1ToMaxOfNDigitsRecursively(char* number, int length, int index)
    {
        if(index == length - 1)
        {
            PrintNumber(number);
            return;
        }
     
        for(int i = 0; i < 10; ++i)
        {
            number[index + 1] = i + '0';
            Print1ToMaxOfNDigitsRecursively(number, length, index + 1);
        }
    }

    简单明了!!!

    PS:对全排列的递归实现,值得关注与记忆!!!

    清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己 -- 共勉
  • 相关阅读:
    Zepto源码分析-动画(fx fx_method)模块
    CSS3用法理解
    移动端网页meta设置和响应式
    javascript基础-正则表达式
    net core 2.x
    angular
    .net core 2.x
    .net core 2.x
    DDD
    DDD
  • 原文地址:https://www.cnblogs.com/hello-yz/p/3251011.html
Copyright © 2020-2023  润新知