现在的位置: 首页 > 综合 > 正文

【有趣的面试算法题】之四 求最小不重复数,源于百度2014届校园招聘软件研发岗位深圳站

2013年12月04日 ⁄ 综合 ⁄ 共 1157字 ⁄ 字号 评论关闭

        百度2014届校园招聘软件研发岗位深圳站的笔试中有这样一题:输入一个任意正整数,输出一个比输入值要大但又不重复的最小数(不重复是指:相邻两个数字不相同,例如1101是重复,1234不重复,1201不重复),比如输入1234,应当输出1235,而不是
1232、1236、4321等。


分析思路:

一,考虑数值区间。尽量选择一个容器比较大的类型,以便不溢出,unsigned long long就比较适合。当然,也可以考虑数组/字符串形式表示任意大的数值,只是,题目只是讲“输入一个任意正整数”,所以我们在接口上也就暂不考虑这种形式。


二,数值表达形式。虽然接口上没有采用以数组/字符串形式表示数值,但我们应当在程序内部考虑这一形式,方便“不重复检查。


三,先保大再不重。从数值的最高位起,两两检查是否相同,如果相同,则在低位加一,并检查级联进位情况,记录最后有加一操作的位置。
从这一位置开始【不包含它本身】向低位方向,顺次按010101...规律填充,如此保证取值最小。


代码示例:

/*
将数值数组中指定位置值加一,并返回向前推进到的位置
由调用者保证数组中的最高位的前一位为0值
*/
int addOne2NumArray(char num[], int p)
{
    while (true)
    {
        if (num[p] < 9)
        {
            ++num[p];
            break;
        }
        else
        {
            num[p]=0;
            ++p;
        }
    }
    return p;
}

/*
算法入口, 获得“最小但不重复数”

*/
uint64 getMyNum(const uint64 N)
{
    
    const int maxNumLength = 64;
    char num[maxNumLength];
    //将数分解到数组中
    int H =0; //记录数值的最高位    
    uint64 tmpN =N;
    while (tmpN)
    {
        num[H] = tmpN % 10;
        tmpN /= 10;
        ++H;
    }
    num[H] =0; //此处重要,预设数值结束位,方便后续操作

    //从高至低 检查数字是否有重复
    int L =H -2; //记录数值中相同的位置
    for (; L >= 0; --L)
    {
        if (num[L] == num[L+1])
        {            
            break;
        }
    }

    //在重复数位处的低位加一    
    
    L=addOne2NumArray(num, (L<0)?0:L);
    
   
    //检查有进位的,是否又和前面的重复
    while (true)
    {
        if (num[L] == num[L+1])
        {
            L =addOne2NumArray(num, L);
        }
        else
        {
            break;
        }
    }


    //从有进位的起,后面的数据尽量取小
    for (int i = L -1; i >= 0; --i)
    {
        num[i] = !num[i +1] ; // num[i +1]==0 也可以
    }

    //组装数据输出
    for (int i = H; i >= 0; --i)
    {
        tmpN = tmpN *10 + num[i];
    }

    return tmpN;
}


测试结果:



抱歉!评论已关闭.