百度14年笔试 - 找出大于某值的最小的不重复数

百度14年校招笔试题:

n 为正整数,求比这个数大且最小的不重复数,重复数为相邻两位数字不相同

如: n = 2222时,输出2301


解题思路:(受insistGoGo 启发,博文地址http://blog.csdn.net/insistgogo/article/details/12240495, 在此表示感谢)

考察 9898996

若找比此数大且最小的不重复数,直接找到此数序列中(从高位开始)首个重复的数字(这里是99),并且将重复数字的低位自增1,如果有进位则进位

这样操作出来会得到一个新数(这里是9899006),得到的新数可能会有新的重复数字出现,对其做同样操作,直到不产生新的重复数字为止

然后将最后一次自增位之后的数字序列变成0101序列,则得到的数字即为要找的数字


文字叙述可能难以理解,下面让我们考察几个数,来理解查找的过程


1. n (输入的数)本身有重复的数

     如 9898996

     9898996 ---> 9899006 (查找到首个重复数字99,然后对99的低位9自增1) --> 9900006 (因为产生新的重复数字,所以做同上操作) --> 10000006 

      --> 10100006 (首个重复数字00,自增1) --> 10101010 (没有产生新的重复数字,将01之后的数字序列变成0101序列)

     则10101010 就是 大于 9898996 且是最小的不重复数

 

    如 85499

    85499 --> 85500 --> 85600 --> 85601

    

    如 8325996

    8325996 --》 8326006 --》 8326010

     

     以上都是对99重复的例子,很容易发现,如果数字序列中出现99,则对99做自增后,会影响到99之前的两位

    

      其他重复例子:如56332

      56332 --》 56340

      如 56443  --》 56450

      很容易发现 00 - 88 的重复属于同一类型的, 只需对重复数字的低位自增,然后将后续序列换成0101序列


2. n (输入的数)本身无重复的数

   本身无重复的数,是不是直接自增1就可了(既最后一位自增1)? 情况并没有这么简单

   如 36954  自增1 变成 36955 (自增1,产生新的重复数字)

   如 36549 自增1 变成 36550 (自增1,产生新的重复数字)

   如 36539 自增1 变成 36540 (这个尾数也是9呢,但自增1之后,就是要找的数啦)

   还有如呢,我还没菊丸栗子呢

   如 36956 这种最喜欢啦 因为自增1 查找就结束了   36957 就是要找的


好了,栗子举玩了(谁给我买我最喜欢的板栗啊,都被我举完了哇 呜呜呜~~~)。

透过栗子,我想应该也能发现些什么了吧(发现啥? 规律规律规律啊)

总结一下:
1. n 本身包含重复,重复的类型有两种:
 1-1  : 99  :自增1 之后,会影响到前两位数字,所以在自增之后,指针(用两指针指向当前的两位被考察数字,如99)需向前移动两位,确认是否产生新的重复数字

1-2   : 00 - 88:喜欢这个重复,因为自增1之后,不会影响到前位数字(既指针不需前移),替换后续序列为0101,就可以退出了


2. n本身不包含重复,类型有三种:

 2-1  :  (x+1)x9,末尾为9,自增1之后,会影响到前一位数字,指针需向前移动1位(两个指针都前移),查看是否产生新的重复数字,若产生,则变为 1中重复情况

2-2   :   (x+1)x,尾数为x,而前一位比其大1,自增1,会产生新的重复数字,指针不需向前移动,变为1中重复情况

2-3   :   x9 和 yx,x9中的x的前一位数不比x大1,yx不满足2-1 和 2-2中要求,且x不为9, 可直接自增1,然后找到所要找的数,退出。


好了,理解以上的内容,就可以编码实现。

此算法复杂度为O(m),m为n的位数。

用两个指针fpStrNum 和 spStrNum分别指向数的最高位和次高位。

#include <iostream>
#include <cstdlib>
#define MAX 100

using namespace std;

char* getStrNum(int nNum)
{
    char *pStrNum = new char[MAX];
    memset(pStrNum, 0, sizeof(char)*MAX);
    int i=0;
    while(nNum)
    {
        pStrNum[i++] = nNum % 10 + '0';
        nNum = nNum / 10;
    }
    
    return pStrNum;
}

void increase(char *p)
{
    if(0==*p) *p = 1+'0';
    else {
        if(*p<'9') *p += 1;
        else {
            *p = '0';
            increase(p+1);
        }
    }
}

void set01(char *start, char* end)
{
    int flag = 0;
    while(start >= end)
    {
        if(flag == 0)
        {
            *start = '0';
            flag = 1;
        }
        else {
            *start = '0' + 1;
            flag = 0;
        }
        start--;
    }
}

char* MinLargeNumber(int nNum)
{
    char* pStrNum = getStrNum(nNum);
    int length = strlen(pStrNum);
    if(1 == length)
    {
        increase(pStrNum);
        return pStrNum;
    }
    char* fpStrNum = pStrNum + length -1;
    char* spStrNum = pStrNum + length -2;
    while(fpStrNum > pStrNum)
    {
        if(spStrNum > pStrNum && *fpStrNum != *spStrNum)
        {
            fpStrNum--;
            spStrNum--;
            continue;
        }
        
        // 含重复 
        if(*fpStrNum == *spStrNum)
        {
            // 00 - 88 
            if(*spStrNum < '9') {
                increase(spStrNum);
                set01(spStrNum-1, pStrNum);
                break;
            }
            // 99
            else {
                increase(spStrNum);
                fpStrNum += 2;
                spStrNum += 2;
                continue;
            }
        }
        // 不含重复 
        else {
            // (x+1)x9
            if(*spStrNum == '9' && (*(fpStrNum+1) - *fpStrNum) == 1)
            {
                increase(spStrNum);
                fpStrNum += 1;
                spStrNum += 1;
                continue;
            }
            // (x+1)x 
            else if((*fpStrNum - *spStrNum) == 1)
            {
                increase(spStrNum);
                continue;
            }
            // x9 or yx
            else {
                increase(spStrNum);
                set01(spStrNum-1, pStrNum);
                break;
            }
        }
    }
    
    return pStrNum;
} 

int main(int argc, char *argv)
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        char *pStrNum = MinLargeNumber(n);
        int len = strlen(pStrNum);
        char *end = pStrNum+len-1;
        while(end>=pStrNum) printf("%c", *end--);
        printf("\n");
    }
    system("pause");
    return 0;
} 

好啦,收工回家晾衣服



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值