剑指offer---17(打印1到最大n位数)

更多题目请点链接:《剑指offer》目录索引


问题描述:

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

思路1:

(1)此题可归为大数处理问题:n可能很大,打印最大的n位数就存在溢出现象
(2)解决方法:采用高精度算法;使用一个数组arr来表示所要打印的数,将其以字符串的形式存储,并模拟数字加法
(3)加法进位:分析进位时,发现只有9、99、999、9999…….进行加1时,最高位才会发生进位故当加到这些数字时,需要发生进位
(4)最大的n位数:由上面所分析的进位问题,我们发现这些数字发生进位之后,数字就会比当前数字多一位,故这些数字(9、99、999….)为最大的n位数
(5)打印:由于我们将这些数字保存时,arr[0]为高位,如果不做处理,打印2位数时就会打印出这样一系列数:01 02 03 04………为了避免这样的情况,我们加一标记进行判断,从高位开始遍历,当遇到不是字符’0’的字符,即为要打印的数

代码:

void Print1ToMax(int n)
{
    assert(n>0);
    //将数字存放到数组当中
    char* arr = (char*)malloc(sizeof(char)*(n + 1));
    assert(arr);
    memset(arr, '0', sizeof(char)*n);
    arr[n] = '\0';

    while(IncreamNumber(arr)==0)
    {
        //加法到最大数,开始打印
        PrintNumber(arr);
    }
    free(arr);
    arr = NULL;
}

int IncreamNumber(char* arr)
{
    int i = 0, nbit = 0;
    int len = strlen(arr);

    for (i = len - 1; i >= 0; i--)
    {
        //将字符转化为数字
        int sum = arr[i] - '0' + nbit;

        //如果在最低位,进行加法
        if (i == len - 1)
            sum++;

        if (sum >= 10)
        {
            if (i == 0)
            {
                //如果在最高位要进位,表示已经打印到最大数,返回1
                return 1;
            }
            else
            {
                //如果没有在最高位,需要进位,则将进位变量置1
                sum -= 10;
                nbit = 1;
                arr[i] ='0'+sum;
            }
        }
        else
        {
            //如果不需要进位,直接存放到数组中
            arr[i] = sum + '0';
            break;
        }
    }
    return 0;
}


void PrintNumber(char* arr)
{
    int i = 0, flag = 1;
    int len = strlen(arr);

    for (i = 0; i < len; i++)
    {
        if (flag == 1 && arr[i] != '0')
        {
            //当遇到需要的数字时,flag置0
            flag = 0;
        }

        if (flag==0)
        {
            printf("%c", arr[i]);
        }
    }
    printf("\t");


}

思路2:

方法:采用递归排列方式来打印我们所需要的数;
思想:数学中只有0~9这10个数字,不管是1位数还是2位数还是3位数等等,都是这10个数字的排列而来;因此我们只需在相应的位数上排列这10个数字,在打印这些数字
相应位排列:先排列最高位,在排列次高位,直到最低位即可

代码:

void Print1ToMaxR(int n)
{
    assert(n>0);
    //将数字存放到数组当中
    char* arr = (char*)malloc(sizeof(char)*(n + 1));
    assert(arr);
    memset(arr, '0', sizeof(char)*n);
    arr[n] = '\0';
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        //最高位排列
        arr[0] = i + '0';
        Print1ToMaxNumberR(arr, n, 0);
    }

    free(arr);
    arr = NULL;
}

void Print1ToMaxNumberR(char* arr, int  len, int index)
{
    if (index == len - 1)
    {
        PrintNumber(arr);
        return;
    }

    for (int i = 0; i < 10; ++i)
    {
        //在排列次高位到最低位的值
        arr[index + 1] = i + '0';
        Print1ToMaxNumberR(arr, len, index + 1);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值