每日一题(97) - 找出大于某值的最小的不重复数

来源:互联网 发布:微信聊天数据怎么恢复 编辑:程序博客网 时间:2024/06/05 17:48

题目来自百度14年校招天津站笔试题,当时思路混乱导致被虐。

题目:n为正整数,求比这个数大且最小的不重复数,重复数为相邻两位数字相同,如1101为重复数,1231为不重复数。

举例:当n = 2222时,输出2301

方法:

1、暴力解决,最直观的方法

对于每一个大于n个数,都做一次判断,找出第一个满足条件的数。

2、O(m)算法,m为已知正整数的位数。

思路:

(1)先把数字变成字符串,此时字符串低位存储数字的低位。

(2)由高位到低位依次处理(字符串的高位代表着数字的高位),一旦高位某个位置pos正常改变,则从[0,pos - 1]之间的数据可以直接用0和1填充。这里的正常是指,pos位置改变后,对[pos+1,..]之间的数字没有影响,此时的特殊情况为包含"99"的情况。

(3)为了让数最小,可以现在pos - 1填充0,之后交错填充1,这里前提是pos的位置上是一个非0的数,如果是0,则pos - 1填充1,之后交错填充0

(4)把字符串表示的数字变成数字。

时间复杂度:

假设数字长度为m,则数字变字符,遍历数字一遍,之后执行算法是最多遍历数字次数为3便,最后字符变数字遍历一遍,所以时间复杂度为O(m)。

举例:

待处理的数据: 98999

(1) 数字98999变成字符串"99989"

(2)这里假设nCurBit初始化指向8(99989),nLastBit初始化指向9(99989)。

<1> 由于nCurBit不等于nLastBit,则nCurBit指向前一位,即为9,(99989),而nLastBit指向8(99989)。

<2> 此时仍然有nCurBit不等于nLastBit,仍然有nCurBit--,即nCurBit指向9(99989),nLastBit也指向9(99989)

<3> 此时nCurBit等于nLastBit,这是由于我们要求比98999大的数,即nCurBit要++。

<4> 这里比较特殊的一点是,nCurBit已经为9了(99989),再加会向前进位(会影响之前已经处理的位),此时加1后变成90099,其中此次变化影响了三个数,此时待处理的位置应该回退到被影响的位的第一位中(90099),这是因为进位后的某些位可能和原来的某些数字是重复的

<5> 此时nCurBit指向第一个被影响的位置(指向9,即90099nLastBit也指向9(90099),而继续往左处理

<6> 之后,还是采用之前的策略处理,直到某个数加1后,不会对那些已经处理好的数字产生影响,就停止。之后剩余的数字直接填充0或1即可。

貌似说的混乱,凑合瞅瞅。。

代码:

(1)暴力解决

#include <iostream>#include <assert.h>using namespace std;bool IsNoRepetition(int nNum){int nCurBit = 0;int nLastBit = -1;while (nNum){if (-1 == nLastBit){nLastBit = nNum % 10;}else{nCurBit = nNum % 10;if (nCurBit == nLastBit){return false;}nLastBit = nCurBit;}nNum /= 10;}return true;}int MaxNum_Force(int nNum){assert(nNum > 9);while (!IsNoRepetition(nNum)){nNum++;}return nNum;}int main(){int nNum = 0;cin>>nNum;cout<<MaxNum_Force(nNum)<<endl;system("pause");return 1;}

(2)O(n)算法

#include <iostream>#include <assert.h>using namespace std;char* IntToString(int nNum){assert(nNum > 9);int nCur = 0;char* pStrNum = new char[20];memset(pStrNum,0,sizeof(char) * 20);while(nNum){pStrNum[nCur++] = nNum % 10 + '0';nNum /= 10;}return pStrNum;}int StringToInt(char* pStrNum){assert(pStrNum != NULL);int nNewNum = 0;int nLen = strlen(pStrNum);while (nLen >= 1){nNewNum *= 10;nNewNum += (pStrNum[nLen - 1] - '0');nLen--;}return nNewNum;}int MaxNum(int nNum){assert(nNum > 9);char* pStrNum = IntToString(nNum);int nCur = strlen(pStrNum);char cLastBit = pStrNum[--nCur];nCur--;while(nCur >= 0){if (pStrNum[nCur] != cLastBit){cLastBit = pStrNum[nCur--];}else if(pStrNum[nCur] != '9') //nCur位不等于9,则直接加1{pStrNum[nCur]++;break;}else   //nCur位等于9,则会影响前面已经处理的数,需要回退{ while(pStrNum[nCur] == '9'){pStrNum[nCur++] = '0';}//进位if (pStrNum[nCur] == 0){pStrNum[nCur] = '1';}else{pStrNum[nCur]++;}cLastBit = pStrNum[nCur + 1];if (cLastBit != pStrNum[nCur]){break;}}}nCur--;//剩余的位直接填充0或者1while (nCur >= 0){if (pStrNum[nCur + 1] == '0'){pStrNum[nCur] = '1';}else{pStrNum[nCur] = '0';}nCur--;}int nNewNum = StringToInt(pStrNum);delete[] pStrNum;return nNewNum;}int main(){int nNum = 0;cin>>nNum;cout<<MaxNum(nNum)<<endl;system("pause");return 1;}

原创粉丝点击