百度2014校招筆試題目題解(更新了第1題的演算法,10.9下午)

來源:互聯網
上載者:User

                                                                     ----武漢站,9.28號百度校招筆試題目演算法題目部分

(題解非官方,僅供參考,轉載請聯絡博主,有錯誤的地方望指正!謝謝)

給定任意一個正整數,求比這個數大且最小的“不重複數”,“不重複數”的含義是相鄰兩位不相同,例如1101是重複數,而1201是不重複數。

 這道題目我也沒有什麼特別出彩的演算法,就是按照常規思路來求解,首先要理解什麼叫做“不重複數”,這是解題的關鍵之一,相鄰兩位不相同的數即為“不重複數”;還有一個地方要注意的就是“求比這個數大且最小的”,就是在比給定數大的不重複數中找到最小的!理解了這兩個地方,這道題目就可以著手求解了!

因為可以直接定位到“重複”的數位的位置,比如12344,我們可以直接定位到個位元4和十位元4上面,然後在低數假設是對整數12199呢?”;

這裡又產生一個問題,因為“重複“的數位可能不止一對,有可能有多對,比如整數11233,定位“33”之後變為“34”,定位“11”之後變為“12”,結果就是12234。又有重複的地方,就是“22”。繼續拿到迴圈去重複;

還有要注意的是,你的程式的設計,是如何儲存數位的值的,是一個一個數位的值求出來呢?還是像我這樣設定一個前後索引?把每個數位的值求出來並且儲存,程式會變得繁瑣複雜,不易讀懂,如果是設定前後索引,則要注意程式退出迴圈的條件!

數位“重複”的定位和變換,是從高位到低位,還是從低位到高位呢?正確的應該是從高位到低位,這給我們的程式設計也帶來了不便。

/*    給定任意一個正整數,求比這個數大且最小的“不重複數”,“不重複數的含義是相鄰兩位不相同,例如1101是不重複數”*/#include <stdio.h>#include <stdlib.h>int getNumNonrepetition(const int NumGived){    int flag = 0;//為0表示該數不是“不重複數”    int numRepeat = NumGived;    int numTemp = 0;//    int currentBit = 0, lastBit = 0;//前後數位索引    while(1)    {        numRepeat++;        //初始化後索引        numTemp = numRepeat;        lastBit = numTemp % 10;        numTemp /= 10;        flag = 1;        //判斷該數是不是“非重複數”        while(numTemp != 0)        {            currentBit = numTemp % 10;            numTemp /= 10;            if(lastBit == currentBit)            {                flag = 0;                break;            }            lastBit = currentBit;        }        if(flag == 1)//該數為不重複數,返回        {            return numRepeat;        }    }}int main(void){    int NumGived = 19922884;    int result = getNumNonrepetition(NumGived);    printf("the number is %d\n", result);    return 0;}


簡單加1的演算法,效率太低,看到這麼多的朋友的評論,大家的演算法大同小異,我也寫了一個演算法,拿出來和大夥分享。

演算法:

1、把整數放到字元數組裡面去,從高位為低位(用變數i)掃描,找到重複的數位,重複數位為“99”跳到第2步,否則跳到第3步,若沒有重複的數位,則該數為不重複數,返回;

2、遇到“99”的重複數,則把“99”改為“00”,然後在“99”前面一位字元加1,把掃描的地方定位在“99”往高位方向的第2位,比如是1299,變換後為1300,然後把掃描變數

3、遇到非“99”的重複數,則直接在低位加1,後面依次變為010101……,結果就是最小的不重複數,返回改值;

至於前面說的一些痛點,真是害怕誤導了大家,畢竟總有考慮不到的地方,希望見諒!

#include <stdio.h>#include <stdlib.h>#include <string.h>#define SIZE 100int getNumNonrepetition(const long long  NumGived, char NumStr[]){    int NumTmp = NumGived;    int NumLength = 0;    int i = SIZE - 1;    //把整數放到字元數組裡面去,從後往前放,比如1234,    //那麼數組NumStr[96] = 1  NumStr[97] = 2  NumStr[98] = 3  NumStr[99] = 4, SIZE = 100    do    {        NumStr[i] = NumTmp % 10 + '0';        NumTmp /= 10;        i--;    }while(NumTmp != 0);    NumLength = SIZE - i - 1;//計算整數的位元    int flag = 0;//設定010101的時候用的變數    i = SIZE - NumLength;    while( 1 )    {        //定位到重複的位上面,下標i + 1為低位,此時NumStr[i] == NumStr[i + 1]        while(i + 1 < SIZE && NumStr[i] != NumStr[i + 1]) i++;        if(i == SIZE - 1) break;//掃完一遍,沒有重複的,跳出迴圈,該數是不重複數        if(NumStr[i + 1] == '9')//重複的數位為99這種情況,將這兩位全部置0,高位加1        {            NumStr[i + 1] = '0';            i--;            NumStr[i + 1] = '0';            i--;            NumStr[i + 1] += 1;        }        else//重複的        {            //低位加1            NumStr[i + 1] += 1;            i += 2;            flag = 0;            //後續全部設為0101……,這個時候肯定是不重複數了,所以可以跳出迴圈            while( i < SIZE )            {                NumStr[i] = flag % 2+ '0';                flag++;                i++;            }            break;        }    }    //列印最小的”不重複數“    int start = SIZE - NumLength;    //如果是99開頭的數字,高位可能會進位,判斷是否為零,不為零則有進位,需列印出來    if(NumStr[start - 1] != '0') putchar(NumStr[start - 1]);    for(i = start; i < SIZE; i++ )    {        putchar(NumStr[i]);    }    return 0;}int main(void){    long long  NumGived = 119998989;    char NumStr[SIZE];    memset(NumStr, '0', SIZE * sizeof(char));    getNumNonrepetition(NumGived, NumStr);    return 0;}


題目指出“N很大”,就是提示我們不要想通過遍曆的方法來找到這個字串,我想到的就一種解法,時間複雜度應該不高,但是我算不出來這個演算法的複雜度是多少,首先說一下什麼是迴文字串:迴文字串是指從左至右和從右至左相同的字串,比如"1221"或者“12321”都是迴文字串。剛好舉得這兩個迴文字串的例子就是我的演算法的兩個類別:

演算法的思想是從第2個字元直到倒數第2個字元遍曆,每遇到一個字元,就依次判斷這個字元前後的字元是否相等,如果相等,則繼續判斷下一個字元,直到以這個字元為中心的兩邊對稱的字元不相等為止,或者前後字元的位置數組越界為止;計算此時的迴文字串的長度,與之前的比較,記下較長的迴文字串的長度和中心字元的位置;遍曆結束則返回最大長度和中心字元的位置

演算法思想同上,其實是一樣的過程!圖解也是一樣的!

/*    長度為N(N很大)的字串,求這個字串裡的最長迴文子串。*/#include <stdio.h>#include <stdlib.h>#include <string.h>//第一類“12321”:中間是一個單獨的字元int  FindLongPaliSubstr_Odd(const char A[], int * indexMid){    int i = 0, cnt = 0;//cnt表示前後移動位元    int MyMax = 0;    int lenOfA = strlen(A);    *indexMid = 0;    for(i = 1; i <= lenOfA - 2; i++)    {        cnt = 0;        while(i - cnt >= 0 && i + cnt <= lenOfA - 1 && A[i - cnt] == A[i + cnt])        {            cnt++;        }        cnt--;        //找到較大長度的迴文字串,儲存中心字元的位置        if(MyMax < 2 * cnt + 1)        {            MyMax = 2 * cnt + 1;            *indexMid = i;        }    }    return MyMax;}//第二類“12321”:中間是兩個相同的字元。int  FindLongPaliSubstr_Even(const char A[],int * First){    int i = 0, cnt = 0;//cnt表示前後移動位元    int MyMax = 0;    int lenOfA = strlen(A);    *First = 0;//中間兩個相同字元的第一個字元位置    for(i = 0; i <= lenOfA - 2; i++)    {        if(A[i] == A[i + 1])        {            cnt = 1;            while(i - cnt >= 0 && (i + 1 + cnt) <= lenOfA - 1 && A[i - cnt] == A[i + 1 + cnt])            {                cnt++;            }            cnt--;            //找到較大長度的迴文字串,儲存中心第一個字元的位置            if(MyMax < 2 * cnt + 2)            {                MyMax = 2 * cnt + 2;                *First = i;            }        }    }    return MyMax;}int main(void){    char A[] = "adfadfbadfdg12321fagage";    int indexMid = 0;    int First = 0;    int i = 0;    //兩種類別的最長迴文子串的長度    int MaxOdd = FindLongPaliSubstr_Odd(A, &indexMid);    int MaxEven = FindLongPaliSubstr_Even(A, &First);    printf("indexMid = %d\n", indexMid);    printf("First = %d\n", First);    //哪類比較大,輸出哪一類的迴文子串    if( MaxOdd > MaxEven)    {        for(i = indexMid - (MaxOdd - 1) / 2; i <= indexMid + (MaxOdd - 1) / 2; i++)        {            putchar(A[i]);        }    }    else    {        for(i = First - (MaxEven - 2) / 2; i <= First + 1 + (MaxEven - 2) / 2; i++)        {            putchar(A[i]);        }    }    return 0;}

 表示連續線段的起點,第二個for迴圈(內迴圈)的計數器 j 從 (i + 1)開始,依次累加Sum,若Sum > L,則記錄點的個數(j - i)中的較大值max;其中,外迴圈,只要遇到的數比L大,就continue,內迴圈,只要遇到的數比L大,就break,這是因為長度為L的繩子是不可能覆蓋這些點的,可以直接跳過!

/*    數軸上從左至右有n個點a[0],a[1],...,a[n - 1],給定一根長度為L的繩子,求繩子最多能覆蓋其中幾個點。*/#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 8int MaxTimesOfL(int A[], int L){    int i = 0, j = 0;    int *arr = (int *)malloc(sizeof(int) * (N - 1));    memset(arr, 0, sizeof(int) * (N - 1));    //初始化數組arr,兩點間的距離為一個數組元素    for(i = 0; i < N - 1; i++)    {        arr[i] = A[i + 1] - A[i];    }    //輸出該數組    for(i = 0; i < N - 1; i++)    {        printf("%-3d", arr[i]);    }    int MaxTimes = 0;    int Sum = 0;    //遍曆找到覆蓋的最多點數    for(i = 0; i < N; i++)    {        if(arr[i] > L)//遇到比L大的數則跳過        {            continue;        }        Sum = arr[i];        for(j = i + 1; j < N - 1; j++)        {            if(arr[j] > L)//遇到比L大的數則跳過,這一句對於程式來說加與不加都一樣            {                break;            }            Sum += arr[j];            if(Sum > L)            {                break;            }        }        MaxTimes = (MaxTimes > (j - i)) ? MaxTimes : (j - i);    }    return (MaxTimes + 1);//因為是線段,所以要加1表示覆蓋的點數}int main(void){    int A[] = {-1, 0, 3, 9, 11, 13, 14, 25};    int L = 5;    int result = MaxTimesOfL(A, L);    printf("\nthe max times is %d\n", result);    return 0;}

#include <stdio.h>#include <stdlib.h>int main(void){    int front = 0 , rear = 0;//設定首尾指標索引    int cnt = 8;    int L = 15;//繩子長度    int MaxTimes = 0;    int arr[] = {-1, 0, 3, 9, 11, 13, 14, 25};//數軸上的點    while(front < cnt)    {        //比L小,則計算MaxTimes,作front++;        if(arr[front] - arr[rear] <= L)        {            MaxTimes = MaxTimes > (front - rear) ? MaxTimes : (front - rear);            front++;        }        else//比L大,rear++;        {            rear++;        }    }    printf("the max times is %d\n", MaxTimes + 1);//第一個數是沒有參與計數的,所以要在最後加1    return 0;}


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.