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

记录来自《剑指offer》上的算法题。

题目如下:

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

第一种解法是比较容易想到,但是遇到大数问题的时候会有溢出的问题,其代码如下:

// 简单的解法,但遇到输入值很大时会出现问题
void Print1ToMaxOfNDigits_1(int n){int number = 1;int i = 0;while (i++ < n)number *= 10;for (i = 1; i < number; i++)cout << i << " ";cout << endl;
}

所以这里需要表达一个大数。最常用也是最容易的方法是用字符串或数组表达大数。下面使用字符串来表达大数。解法代码如下:

bool Increment(char* number){bool isOverflow = false;int nTakeOver = 0;int nLength = strlen(number);for (int i = nLength - 1; i >= 0; i--){int nSum = number[i] - '0' + nTakeOver;if (i == nLength - 1)nSum++;if (nSum >= 10){if (i == 0)isOverflow = true;else{nSum -= 10;nTakeOver = 1;number[i] = '0' + nSum;}}else{number[i] = '0' + nSum;break;}}return isOverflow;
}
// 打印用字符串表示的数字
void PrintNumber(char* number){bool isBeginning0 = true;int nLength = strlen(number);for (int i = 0; i < nLength; ++i){if (isBeginning0 && number[i] != '0')isBeginning0 = false;if (!isBeginning0)printf("%c", number[i]);}printf("\t");
}// 利用字符串来表达大数
void Print1ToMaxOfNDigits_str(int n){if (n <= 0)return;// 初始化为'0'char *numbers = new char[n + 1];memset(numbers, '0', n);numbers[n] = '\0';while (!Increment(numbers)){PrintNumber(numbers);}delete[] numbers;
}
// 测试
int main(void){int t[] = { 0, 1, 3, -1 };for (int i = 0; i < 4; i++){cout << "test num=" << t[i] << ": \n";Print1ToMaxOfNDigits_str(t[i]);cout << endl;}system("pause");return 0;
}

这种解法中,函数Increment()实现在表示数字的字符串numbers上增加1,并判断是否出现溢出问题,也就是是否达到最大的n位数,而PrintNumber()函数则是打印出numbers

其中在函数Increment()中,每次增加1后快速判断是否到了最大的n位数的办法是判断第一个字符是否产生了进位,因为只有达到最大的n位数的情况才会对第一个字符(下标是0)进行进位,如n=3,只有对999再加1,才会对第一个字符进行进位,在函数中的体现就是在如下代码:

if (nSum >= 10){if (i == 0)isOverflow = true;....
}

这种解法思路比较直观,但是由于模拟了整数的加法,代码有点长,下面换另一种思路。如果我们在数字面前补0,可以发现n位所有十进制数其实就是n个从0到9的全排列。也就是说,我们把数字的每一位都从0到9排列一遍,就可以得到所有的十进制数。

全排列用递归很容易表达,数字的每一位都是0到9中的一位,然后设置下一个数。递归结束的条件是已经设置了数字的最后一位。代码如下:

// 递归方法
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);}
}
// 利用字符串来表达大数
void Print1ToMaxOfNDigits_str(int n){if (n <= 0)return;// 初始化为'0'char *numbers = new char[n + 1];//memset(numbers, '0', n);numbers[n] = '\0';/*while (!Increment(numbers)){PrintNumber(numbers);}*/for (int i = 0; i < 10; ++i){numbers[0] = i + '0';Print1ToMaxOfNDigitsRecursively(numbers, n, 0);}delete[] numbers;
}

上述代码中注释掉的是第二种解法中的代码,然后增加适用于递归方法的代码。

更完整例子看出我的Github。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/408974.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java判断闰年通过多态方法_04748《Java语言程序设计》实验指导书.doc

04748《Java语言程序设计》实验指导书.docJava语言程序设计实验指导书前言一、上机实验目的上机实验的目的是提高学生的分析问题、解决问题的能力和动手能力&#xff0c;通过实践环节理解 Java语言的基本结构和程序设计方法。通过亲手编程掌握 Java 程序设计编程的方法。二、实…

利用宏定义在编译阶段检查结构体大小的方法

http://blog.csdn.net/crazycoder8848/article/details/8292770 typedef struct {char a[100]; } T_XXX;typedef struct {char a[99]; } T_QQQ;/* 检测结构体的大小是否等于特定值 */ #define SIZE_OF_TYPE_EQUAL_TO(type, size) \ static inline char size_of_##type##_eq…

剑指offer--在O(1)时间内删除链表结点

记录来自《剑指offer》上的算法题。 题目如下&#xff1a; 给定单向链表的头指针和一个结点指针&#xff0c;定义一个函数在O(1)时间删除该结点。 结点定义如下&#xff1a; struct ListNode{int m_nValue;ListNode* m_pNext; }; 最常规的删除链表结点方法是从头结点开始遍历…

Designer设计无代码工作流

1. 打开Designer&#xff0c;选择工作流&#xff0c;选择列表工作流&#xff0c;选择你要将此工作流应用的列表&#xff08;这里我选择报销单&#xff09;。 填写好工作流名称&#xff0c;点击确定。 现在我们开始正式设计工作流&#xff0c;首先我们拉一个记录历史到工作流中&…

剑指offer--调整数组顺序使奇数位于偶数前面

记录来自《剑指offer》的算法题。 题目如下&#xff1a; 输入一个整数数组&#xff0c;实现一个函数来调整该数组中数字的顺序&#xff0c;使得所有奇数位于数组的前半部分&#xff0c;所有偶数位于数组的后半部分。 最简单的思路就是从头开始扫描整个数组&#xff0c;当碰到偶…

java proguard 使用_使用proguard混淆java9代码

序本文主要研究一下如何使用proguard混淆java9代码mavencom.github.wvengenproguard-maven-pluginpackageproguard6.0.1${project.build.finalName}.jar${project.build.finalName}.jar!META-INF/maven/**,!module-info.classtrue${project.basedir}/proguard.cfg${java.home}/…

75个移动App开发教程

原文地址&#xff1a;http://www.goodfav.com/zh/app-development-tutorials-3559.html 移动应用程序开发是大企业和创意的个人和小团队开发&#xff0c;是一个有很多商业机会的领域之一。它可能需要多次尝试设计来实施一个出类拔萃的应用程序&#xff0c;但是&#xff0c;如果…

机器学习算法总结--线性回归和逻辑回归

1. 线性回归 简述 在统计学中&#xff0c;线性回归&#xff08;Linear Regression&#xff09;是利用称为线性回归方程的最小平方函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析。这种函数是一个或多个称为回归系数的模型参数的线性组合&#xff08;自变量都…

java 对应sql驱动版本_关于Oracle JDBC驱动版本、JDK版本、数据库版本对应关系(相关的报错:ORA-28040)...

关于Oracle JDBC驱动版本、JDK版本、数据库版本对应关系说明&#xff1a;1、Oracle JDBC驱动版本查看方式(Oracle JDBC驱动程序随Oracle数据库服务器一起提供)(用户&#xff1a;Oracle”)&#xff1b;$cd $ORACLE_HOME/jdbc/libojdbc5.jarojdbc6.jar2、JDK版本查看方式&#xf…

Thinking in java之前

开始写博客了&#xff0c;从哪里开始呢&#xff0c;因为是抱着学习的态度开始写&#xff0c;所以选择用java开始。很多人说C语言是最适合入门的语言&#xff0c;不知道为什么&#xff0c;我却一直觉得java是入门语言首选。 java是简单的&#xff0c;健壮的&#xff0c;灵活的。…

C++知识总结(1)--变量和基本类型

最近打算看看《C primer》&#xff0c;重新复习C的一些知识点&#xff0c;同时会添加部分在做牛客网编程题目时候记录的知识点。 变量和基本类型 endl操纵符的效果是结束当前行&#xff0c;并将与设备关联的缓冲区中的内容刷到设备中。缓冲刷新操作可以保证到目前为止程序所产…

coroutine php_PHP 协程实现

多进程/线程最早的服务器端程序都是通过多进程、多线程来解决并发IO的问题。进程模型出现的最早&#xff0c;从Unix 系统诞生就开始有了进程的概念。最早的服务器端程序一般都是 Accept 一个客户端连接就创建一个进程&#xff0c;然后子进程进入循环同步阻塞地与客户端连接进行…

ORACLE PL/SQL编程之八: 把触发器说透

本篇主要内容如下&#xff1a; 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 触发器触发次序 8.2.2 创建DML触发器 8.2.3 创建替代(INSTEAD OF)触发器 8.2.3 创建系统事件触发器 8.2.4 系统触发器事件属性 8.2.5 使用触发器谓词 8.…

机器学习算法总结--决策树

简介 定义&#xff1a;分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点和有向边组成。结点有两种类型&#xff1a;内部结点和叶结点。内部结点表示一个特征或属性&#xff0c;叶结点表示一个类。 决策树学习通常包括3个步骤&#xff1a;特征选择、决策树的生…

mac终端查看php版本_Mac切换php版本方法

本文主要和大家分享Mac切换php版本方法&#xff0c;希望能帮助到大家。1.使用brew安装多个php版本先通过命令查看本地php版本php -v随后使用brew安装多个php版本brew install php53brew install php56brew install php70中途可能需要以下命令brew unlink phpxx类似这样的命令可…