《剑指offer》17--打印从 1 到最大的 n 位数[C++]

本文介绍了一种使用回溯法和模拟加法的方法来打印从1到最大的n位十进制数,解决了当n非常大时无法直接用整型变量表示的问题。通过C++代码实现,详细解释了递归过程和加法模拟,同时提供了Java解法对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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

解题思路

由于 n 可能会非常大,因此不能直接用 int 表示数字,而是用 char 数组进行存储。

使用回溯法得到所有的数。

模拟加法

#include <iostream>

using namespace std;

void PrintMaxNDigits(int n);
void PrintToMaxNDigits(char *number, int index);
void PrintNumber(char *number);

int main() {
    int n;
    while(cin>>n) PrintMaxNDigits(n);
    return 0;
}

void PrintMaxNDigits(int n) { //n位上的0-9的全排列问题
    if (n <= 0) return;
    char *number = new char[n + 1];
    memset(number, '0', n);
    number[n] = '\0'; //末尾,用字符串时,高位在前,低位在后存
    while(!Increment(number)) PrintNumber(number);
    delete[]number;
}
 
void Increment(char *number) { //加法模拟
    bool IsOF =false;
    int CV = 0, len = strlen(number);
    for(int i = len-1; i>=0; --i) {
        int sum = number[i]-'0'+CV;
        if(i == len-1) sum++;
        if(sum >= 10) {
            if(i == 0) IsOF = true;
            else {
                sum -= 10;
                CV = 1;
                number[i] = '0'+sum;
            }
        } else {
            number[i] = '0'+sum;
            break;
        }
    }
    return IsOF;
}

void PrintNumber(char *number) { //输出 
    int len=strlen(number); 
    bool tag=true; 
    for(int i=0; i<len; i++) { 
        if(tag&&number[i]!='0') tag=false; //高位为0的不输出 
        if(!tag) cout<<number[i]; 
    } 
    if(!tag) cout<<endl; 
}
 

全排列

#include <iostream>

using namespace std;

void PrintMaxNDigits(int n);
void PrintToMaxNDigits(char *number, int index);
void PrintNumber(char *number);

int main() {
    int n;
    while(cin>>n) PrintMaxNDigits(n);
    return 0;
}

void PrintMaxNDigits(int n) { //n位上的0-9的全排列问题
    if (n <= 0) return;
    char *number = new char[n + 1];
    number[n] = '\0'; //末尾,用字符串时,高位在前,低位在后存
    PrintToMaxNDigits(number, n, 0); //已修改,比之前更简洁 
    delete[]number;
}
 
void PrintToMaxNDigits(char *number, int index) { //递归的过程
    int len = strlen(number);
    if (index == len) {   //递归终止条件
    	PrintNumber(number);  //打印出当前的数字 
    	return;
    }
    for (int i = 0; i < 10; i++) {  //递归分支,当前数取0~9 
    	number[index] = i + '0';
    	PrintToMaxNDigits(number, len, index + 1);  //递归深度
    }
}

void PrintNumber(char *number) { //输出 
    int len = strlen(number), index = 0;;
    while(index < len && number[i] == '0') ++index; //高位为0的不输出
    if(index < len) {
        while(index < len) cout << number[i]; 
        cout << endl;
    }
}

类似题目: 

打印从1到最大的n位数_牛客题霸_牛客网【牛客题霸】收集各企业高频校招笔面试题目,配有官方题解,在线进行百度阿里腾讯网易等互联网名企笔试面试模拟考试练习,和牛人一起讨论经典试题,全面提升你的技术能力icon-default.png?t=M0H8https://www.nowcoder.com/practice/4436c93e568c48f6b28ff436173b997f?tpId=13&tqId=2273153&ru=/practice/11662ff51a714bbd8de809a89c481e21&qru=/ta/coding-interviews/question-ranking

【Java解法】

import java.util.*;
public class Solution {
    public int[] printNumbers (int n) {
        int max = power(n) - 1;
        int[] res = new int[max];
        for (int i=0; i<max; i++) {res[i] = i+1;}
        return res;
    }

    private int power(int n) {
        int tmp = 1;
        for (int i=0; i<n; i++) {tmp *= 10;}
        return tmp;
    }
}

参考文献

[1]  CS-Notes

[2] 【LeetCode & 剑指offer刷题】发散思维题1:17 打印从1到最大的n位数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贫道绝缘子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值