剑指offer之打印1到最大的n位数

1.题目描述

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

2.分析

  1. 如果简单的使用int或者long long类型来打印出结果,那么当n很大,比64还大的时候,就会出现溢出,无法打印出来
  2. 应该使用字符串来模拟数字加分,才可能没有数字长度限制

3.模拟加减法解法

A.源码–使用vector<char> 来保存数据
#include <memory>
#include <cstring>
#include <vector>
#include <iostream>
using  namespace std;
class Digit
{
    friend ostream& operator<<(ostream& os,const Digit& digit);
public:
    //是否溢出判断
    bool isOverflow;
    Digit(){}
    Digit(const int n):isOverflow(false){_digit = std::move(vector<char>(n,'0'));}

    Digit& operator ++()
    {
        isOverflow = false;
        //使用反向迭代器进行模拟计算
        auto rbegin_iter = _digit.rbegin(),rend_iter = _digit.rend();
        for(auto reiter = rbegin_iter;reiter!=rend_iter;++reiter)
        {
            int number = *reiter - '0' ;
            if(reiter == rbegin_iter)
                ++number;
            if(number >=10)
            {
                number -=10;
                if( reiter+1 != rend_iter)
                    *(reiter+1) +=1;
                else
                    isOverflow = true;
            }
            *reiter = number + '0';
        }
        return *this;
    }
    Digit& operator =(const Digit& rhs)
    {
        this->_digit = rhs._digit;
        this->isOverflow = rhs.isOverflow;
        return *this;
    }

    Digit operator ++(int)
    {
        Digit preDigit;
        preDigit = *this;
        ++(*this);
        return preDigit;
    }
private:
    vector<char> _digit;

};
//输出字符串vector<char> _digit
ostream& operator<<(ostream& os,const Digit& digit)
{
    int length = digit._digit.size();
    int index = 0;
    while(digit._digit[index]=='0') ++index;
    for(;index<length;++index)
        os<<digit._digit[index];
    return os;
}

void PrintOneToMaxOfNDigits_1(int n)
{
    if (n <= 0)
        return;

    Digit digit(n);
    while(!(++digit).isOverflow)
    {
        cout << digit<<" ";
    }
    cout <<endl;
}
int main()
{
    PrintOneToMaxOfNDigits_1(3);
    return 0;
}

运行结果图:
这里写图片描述

B.源码–使用char* _digit 来保存数据
#include <memory>
#include <cstring>
#include <vector>
#include <iostream>

using namespace std;
class Digit2
{
    friend ostream& operator<<(ostream& os,const Digit2& digit);
public:
    bool isOverflow;
    Digit2(){//初始化_digit
        _digit = new char[1];
        _digit[1] = '\0';
    }
    Digit2(const int n):isOverflow(false)
    {
        //初始化_digit
        _digit = new char[n+1];
        memset(_digit,'0',n);
        _digit[n] = '\0';
    }
    ~Digit2(){delete []_digit;}

    Digit2& operator ++()
    {
        isOverflow = false;
        int length = strlen(_digit);
        for(int index=length-1;index >=0;--index)
        {
            int number = _digit[index] - '0';
            if(index ==length-1)
                ++number;

            if(number>=10)
            {
                number -=10;
                if(index == 0)
                    isOverflow = true;
                else
                    ++_digit[index-1];

            }
            _digit[index] = number + '0';

        }

        return *this;
    }


    Digit2& operator =(const Digit2& rhs)
    {
        if(&rhs !=this)
        {
            delete []this->_digit;
            int length = strlen(rhs._digit);
            this->_digit = new char[length + 1];
            for(int i=0;i<=length;++i)
            {
                this->_digit[i] = rhs._digit[i];
            }
            this->isOverflow = rhs.isOverflow;
        }
        return *this;
    }

    Digit2 operator ++(int)
    {
        Digit2 preDigit;
        preDigit = *this;
        ++(*this);
        return preDigit;
    }
private:
    char* _digit;

};
ostream& operator<<(ostream& os,const Digit2& digit)
{
    int length = strlen(digit._digit);
    int index = 0;
    while(digit._digit[index] == '0') ++index;
    for(;index<length;++index)
        os<<digit._digit[index];
    return os;
}
void PrintOneToMaxOfNDigits_1(int n)
{
    if (n <= 0)
        return;
    Digit2 digit(n);
    while(!(++digit).isOverflow)
    {
        cout << digit<<" ";
    }
    cout  <<endl;
}
int main()
{
    PrintOneToMaxOfNDigits_1(3);
    return 0;
}

运行结果:
这里写图片描述

C.全排列递归–源码
#include <memory>
#include <cstring>
#include <vector>
#include <iostream>
using namespace std;

class Digit
{
    friend ostream& operator<<(ostream& os,const Digit& digit);
public:
    Digit():length(0){_digit=std::move(vector<char>(0));}
    Digit(const int n):length(n){_digit=std::move(vector<char>(n,'0'));}

    vector<char> _digit;
    int length;

};
ostream& operator<<(ostream& os,const Digit& digit)
{
    int index = 0;
    while(digit._digit[index]=='0')++index;
    if(index == digit.length)
    {
        os<<'0';
        return os;
    }
    for(;index!=digit.length;++index)
        os<<digit._digit[index];
    return os;
}
void RecursionPrint1ToN(Digit& digit,int index,bool& isBeginning0)
{
    if(index == digit.length)
    {
        //第一次不打印,第一次是0
        if(isBeginning0)
        {
            isBeginning0 = false;
            return;
        }
        cout << digit<<" ";
        return;
    }
    for(int i=0;i<10;++i)
    {
        digit._digit[index] = '0'+i;
        RecursionPrint1ToN(digit,index+1,isBeginning0);
    }
}
void Print1ToMaxN(int n)
{
    if(n<=0)
        return;

    Digit digit(n);

    //第一次不打印出来,第一个数是0
    bool isBeginning0 = true;
    RecursionPrint1ToN(digit,0,isBeginning0);
}
int main()
{
    //PrintOneToMaxOfNDigits_1(4);
    Print1ToMaxN(8);
}

4.结论

这道题使用了字符串模拟了加法如何加减,使用vector<char> 的效率比char * 低。当n的大小是9,也就是要进行上亿次加法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值