面试题17:打印1到最大的n位数

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

考点:

用字符串或者数组表达一个大数。

思路

1.由于不知道n的范围,n很大的时候,用int或者long long 可能会溢出。

2.用字符串表达大数。'0'-'9',因为是N位的数,用N+1的字符串存储,最后一位保存结束符'\0',前半部分补零。

3.strlen函数用法

function

<cstring>

strlen

size_t strlen ( const char * str );

Get string length

Returns the length of the C string str.

The length of a C string is determined by the terminating null-character: A C string is as long as the number of characters between the beginning of the string and the terminating null character (without including the terminating null character itself).

C字符串的长度由终止空字符确定:C字符串与字符串开头和终止空字符之间的字符数一样长(不包括终止空字符本身)。

This should not be confused with the size of the array that holds the string. For example:

size_t strlen ( const char * str );

defines an array of characters with a size of 100 chars, but the C string with which mystr has been initialized has a length of only 11 characters. Therefore, while sizeof(mystr) evaluates to 100, strlen(mystr) returns 11.

In C++, char_traits::length implements the same behavior.

4.std::char_traits::length 用法

public static member function

<string>

std::char_traits::length

static size_t length (const char_type* s);

Get length of null-terminated string

Returns the length of the null-terminated character sequence s.

The behavior implemented by all character traits types shall be to return the position of the first character for which member eq returns false when compared against charT().

This function is equivalent to strlen (for char) and wcslen (for wchar_t).

Parameters

s

Pointer to a null-terminated character sequence.

Member type char_type is the character type (i.e., the class template parameter in char_traits).

Return Value

Returns the length of s.

size_t is an unsigned integral type.

// char_traits::length
#include <iostream> // std::cout
#include <string> // std::char_traits int main ()
{
const char * foo = "String literal";
std::cout << "foo has a length of ";
std::cout << std::char_traits<char>::length(foo);
std::cout << " characters.\n";
return 0;
}
foo has a length of 14 characters.

代码

void PrintNumber(char* number);
bool Increment(char* number);
void Print1ToMaxOfNDigitsRecursively(char* number, int length, int index);

方法一:不推荐,看懂思路即可

void Print1ToMaxOfNDigits_1(int n)
{
//1.如果小于等于0,直接返回
if (n <= 0)
return;
//2.大数用字符串数组表示,新分配一个n+1长度的字符串数组,最后一位存放结束符'\0'
char *number = new char[n + 1];
//3.memset初始化前n位数为0
memset(number, '0', n);
//4.将数组最后一位赋值'\0'
number[n] = '\0'; //5.重复执行递增字符串函数并打印,直到字符串超过N位数时,停止打印
while (!Increment(number))
{
//5.1 打印字符串函数,前面为0的数不打印。
PrintNumber(number);
}
//6.释放字符串数组内存。
delete[]number;
}
bool Increment(char* number)
{
//1.bool标志是否溢出,初始化false
bool isOverflow = false;
//2.int 进位
int nTakeOver = 0;
//3.记录number的个数,除去结束符
int nLength = strlen(number); //4.加法溢出循环函数,字符串从后往前循环,结束条件:最高位达到10就break
for (int i = nLength - 1; i >= 0; i--)
{
//4.1 nSum=字符串i位的数值+是否进位
int nSum = number[i] - '0' + nTakeOver; //4.2 i为最后一位,就该位数值++,前面字符串不变
if (i == nLength - 1)
nSum++; //4.3 如果这个位置的数值达到了10,说明该进位了
if (nSum >= 10)
{
//4.3.1 如果这个位置刚好是最大位,就不能再进位,就会溢出,设置bool标记为真。这时不再打印。
if (i == 0)
{
isOverflow = true; break;
}
//4.3.2 如果这个位置不是最大位,就进一位
else
{
//4.3.2.1 将数值设为0(nSum-10)
nSum -= 10;
//4.3.2.2 将进位设为1,将加到高位上去
nTakeOver = 1;
//4.3.2.3 将这一位设为0
number[i] = '0' + nSum;
}
}
//4.4 如果没有到达10,将数值+'0'并存入数组[i]中,并跳出循环开始打印。
else
{
number[i] = '0' + nSum;
break;
}
}
//5.返回是否溢出值bool
return isOverflow;
}

方法二:最优解

数字排列,递归

n位所有十进制数:n个从0到9的全排列

1.数字的每一位都可能是0-9的一个数,然后设置下一位。

2.递归结束的条件:已经设置了数字的最后一位。

void Print1ToMaxOfNDigits_2(int n)
{
//1.如果位数小于等于0,就不打印
if (n <= 0)
return;
//2.分配长度为N+1的字符串数组指针new char[n+1],并将末位赋值'\0'结束符
char* number = new char[n + 1];
number[n] = '\0'; //3.设置index=0是0-9的循环
for (int i = 0; i < 10; ++i)
{
//3.1 数组[0]赋值i+'0'
number[0] = i + '0';
//3.2 开始调用递归函数,从index=0开始,依次设置下一位
Print1ToMaxOfNDigitsRecursively(number, n, 0);
}
//4.释放掉数组指针delete[]
delete[] number;
} //递归打印函数void,参数:字符串数组指针char*,长度int,设置位数int,动作:打印函数PrintNumber(number);
void Print1ToMaxOfNDigitsRecursively(char* number, int length, int index)
{
//1.递归结束条件:如果设置到了最后一位,就打印该字符串
if (index == length - 1)
{
//1.1 执行公共函数PrintNumber(number);
PrintNumber(number);
//1.2 返回
return;
} //2. 设置index+1是0-9的循环
for (int i = 0; i < 10; ++i)
{
//2.1 数组[index+1]赋值i+'0'
number[index + 1] = i + '0'; //2.2 使用递归设置下一位,参数index+1
Print1ToMaxOfNDigitsRecursively(number, length, index + 1);
}
}

公共函数

字符串number表示一个数字,数字有若干个0开头

打印出这个数字,并忽略开头的0

void PrintNumber(char* number)
{
    //1.bool标记第一个数是否为0,默认为0
    bool isBeginning0 = true;
    //2.数组的长度,即n位数,不含'\0'
    int nLength = strlen(number);
    //3.从数组[0]开始打印,循环
    for (int i = 0; i < nLength; ++i)
    {
        //3.1 判断该位是否为零:如果当前bool标记为true,即上一位为0,判断这一位是否为0,如果不是0,将新bool标记改为false。
        //if (isBeginning0 && number[i] != '0')
        //    isBeginning0 = false;
        if (isBeginning0)
            isBeginning0 = number[i] != '0' ? false:true;
        
        //3.2 如果该位不为0,就开始打印
        if (!isBeginning0)
        {
            printf("%c", number[i]);
        }
    }     printf("\t");
}

相关题目:前面的代码中,我们都是用一个char型字符表示十进制数字的一位。

8个bit的char型字符最多能表示256个字符,而十进制数字只有0-9的10个数字。

因此用char型字符串来表示十进制的数字并没有充分利用内存,有一些浪费。

有没有更高效的方式来表示大数。

解决方案2:大数据处理时的一种BitMap小算法

可以使用bitmap算法,这个很有意思。特别是在数据量大的时候,非常高效

所谓bitmap就是用一个bit位来标记某个元素对应的value,而key即是这个元素。由于采用bit为单位来存储数据,因此在可以大大的节省存储空间。

解决方案4:

仅供参考:

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

unsigned int iv,i;

unsigned char BCD[5];//定长10位BCD码

unsigned char sv[11];

void main() {

    iv=123456789;//最大10位无符号正整数

    //INT2BCD

    sprintf(sv,"%010u",iv);

    for (i=0;i<10;i+=2) {

        BCD[i/2]=(sv[i]<<4)|(sv[i+1]&0x0F);

    }

    printf("BCD=%02x%02x%02x%02x%02x\n",BCD[0],BCD[1],BCD[2],BCD[3],BCD[4]);

    //BCD2INT

    for (i=0;i<10;i+=2) {

        sv[i]='0'|(BCD[i/2]>>4);

        sv[i+1]='0'|(BCD[i/2]&0x0F);

    }

    sscanf(sv,"%010u",&iv);

    printf("iv=%010u\n",iv);

    getch();

}

解决方案5:

十进制表示方法,不止一种

ASCII

BCD

压缩BCD

这些都是十进制编码,其中压缩BCD可以多存储一倍的数据

其他,

16Bits 可以表示万进制

32Bits 可以表示亿进制,10   亿进制

这些和十进制优势关系密切的表示方法,转换简单

另外一种 多 字节(字,双字,四字)串 表示方法,

是 二进制表示法,

和十进制转换不太方便,不过+,-,*,/ 等数学运算,实现方便.

第17题:打印1到最大的n位数的更多相关文章

  1. 面试题17:打印1到最大的n位数

    // 面试题17:打印1到最大的n位数 // 题目:输入数字n,按顺序打印出从1最大的n位十进制数.比如输入3,则 // 打印出1.2.3一直到最大的3位数即999. 解题思路: 首先是一个大陷阱,n ...

  2. 【Offer】[17] 【打印1到最大的n位数】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入数字n,按顺序打印出从1最大的n位十进制数.比如输入3,则打印出1.2.3一直到最大的3位数即999. 思路分析 要考虑到大数问题, ...

  3. 《剑指offer》第十七题(打印1到最大的n位数)

    // 面试题17:打印1到最大的n位数 // 题目:输入数字n,按顺序打印出从1最大的n位十进制数.比如输入3,则 // 打印出1.2.3一直到最大的3位数即999. #include <ios ...

  4. 打印1到最大的n位数-Java

    在练习剑指offer的时候,第12题打印1到最大的n位数的时候,想找个java版的,但大家要么用BigInteger做,要么给出其他的方法.我觉得要给就给最好的方法,下面是我自己参考C++代码写的ja ...

  5. 【Java】 剑指offer(16) 打印1到最大的n位数

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入数字n,按顺序打印出从1最大的n位十进制数.比如输入3,则打印 ...

  6. 剑指offer 面试17题

    面试17题: 题目:打印从1到最大的n位数 题:输入数字n,按顺序打印出从1到最大的n位十进制数,比如输入3,则打印出1.2.3一直到最大的3位数999. 解题思路:需要考虑大数问题,这是题目设置的陷 ...

  7. 剑指offer编程题Java实现——面试题12打印1到最大的n位数

    题目:打印1到最大的n位数 输入数字n,按顺序打印输出从1到最大的n位十进制数,比如输入3,打印从1到999. 这道题考察的地方是如何表示大数问题.由于n是任意大的数组,如果n太大的话n位数就超过了l ...

  8. 每天一道算法题(15)——打印1到最大的n位数

    题目: 打印1到最大的n位数.如n=4,打印1-9999. 思路: 由于直接使用循环会导致int或者long long都不够存储.因此使用字符串来存储数据,这里涉及到数字转换成字符串以及字符串的加法. ...

  9. 《剑指offer》面试题12:打印1到最大的n位数

    面试题12:打印1到最大的n位数 剑指offer题目12,题目如下 输入数字n,按顺序打印出1到最大的n位十进制数,比如输入3,则打印出1,2,3一直到最大的三位数999 方法一 和面试题11< ...

随机推荐

  1. 谈缓存数据库在web开发中的重要性

    1.开局先抛出如下问题: ①当关系型数据库存放的数据量很大时,每次查询耗时明显变长,那么如何解决该问题? ②当业务要求单用户登录(即同一个账户有一个用户登录后,第二个用户再登录该账户要么挤出之前的登录 ...

  2. mongoose的安装与使用(书签记录) 2017

    Windows7环境下安装:慕课网中的手记 http://www.imooc.com/article/12447 关于在CMD中对Mongo API的调用,从这些API调用中我们也可以更容易地理解在n ...

  3. Unity 行为树-共享变量

    一.引言 有以下小场景: 节点A:发现了 敌人. 节点B:追逐敌人. 对于同一个敌人物体,节点AB之间是如何传递数据 的呢? 行为树节点AB之间,需要一个中间变量Temp来传递数据. A发现了敌人,将 ...

  4. 简单的PHP+Mysql实现分页

    <?php /** * PHP+Mysql实现分页 * **/ ?> <html> <head> <meta http-equiv="Content ...

  5. 华东交通大学2017年ACM“双基”程序设计竞赛 1005

    Problem Description 假设你有一个矩阵,有这样的运算A^(n+1) = A^(n)*A (*代表矩阵乘法)现在已知一个n*n矩阵A,S = A+A^2+A^3+...+A^k,输出S ...

  6. myeclipse9.0安装svn插件

    先得保证myeclipse9.0是可以正常使用的吧. 第一步当然是从网上下载SVN插件啦.myeclipse9.0集成的eclipse版本是属于3.x,所以下载eclipse3.x系列的SVN插件. ...

  7. win10系统添加照片查看器(win7版)

    很多人不习惯win10的照片查看器,还是比较怀念win7版本的照片查看器,通过以下两种方法可以在win10图片上点击右键时,"打开方式"中重现"Windows照片查看器& ...

  8. MySQL存储引擎InnoDB,MyISAM

    MySQL存储引擎InnoDB,MyISAM1.区别:(1)InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语 ...

  9. Java日志格式应该是占位符还是字符串拼接

    背景 ​ 上次在群中,有个群友说自己把所有项目中,所有使用占位符打印日志的方式都修改成为了字符串拼接的方式,因为他曾经看了一篇文章,说字符串拼接的形式比占位符形式的性能更好,这个话题引起了大家的广泛讨 ...

  10. 排序算法对比,步骤,改进,java代码实现

    前言 发现是时候总结一番算法,基本类型的增删改查的性能对比,集合的串并性能的特性,死记太傻了,所以还是写在代码里,NO BB,SHOW ME THE CODE! github地址:https://gi ...