人人校招筆試題


人人校招筆試題

                                             ---9月22日,人人校招筆試題

1、給定一個有序數組a,長度為len,和一個數X,判斷A數組里面是否存在兩個數,他們的和為X,bool judge(int *a, int len, int x),存在返回true,不存在返回false

2、給定有n個數的數組a,其中超過一半的數為一個定值,在不進行排序、不開設額外數組的情況下,以最高效的算法找到這個數:int find(int *a, int n)

 

 

題解:(轉載請聯系博主,個人看法,僅供參考!)

1、給定一個有序數組a,長度為len,和一個數X,判斷A數組里面是否存在兩個數,他們的和為X,bool judge(int *a, int len, int x),存在返回true,不存在返回false

解:  注意仔細研究題目中的條件,比如關鍵的一句,有序數組a,這是一個有序的數組,這一點十分重要!

思路1:遍歷,時間復雜度為O(N2),很顯然,這種方法沒什么實際意義,而且題目中說了這個一個有序數組,采用遍歷的方法是你想不出其他解法時的最壞選擇而已!

思路2:根據有序數組的特點,要么遞增要么遞減,這個時候我們不要憑空想象,拿出紙和筆,舉一個實例來分析是最好的方法,

 

  算法的思路通過上圖可以清晰的表現出來,這里再簡單敘述一下:申請一個與原數組a[N]一樣長度的內存空間arr[N],用給定的值X減去原數組中的元素,對應的放到申請的內存空間arr[N]中,設置兩個指針p和q,分別指向原數組a[N]的最后一個元素和arr[N]的第一個元素,指針移動滿足條件:

指針移動必須滿足條件:p和q指針沒有越界,越界則跳出

  若指針指向的值相等且i不等於j(添加了條件:i不等於j,避免出現8 = 4 + 4的情況),則返回true;

  若原數組是升序的,那么每次移動指向的值較大的指針;

  若原數組是降序的,那么每次移動指向的值較小的指針;

移動結束,跳出移動指針的循環,說明不存在,返回false

  在網友( Tyler_cao泡泡騰)的評論中有更加簡潔的方法,思路基本一樣,借鑒一下!

code:

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Judge(int *a, int len, int x)
{
    int Ascending = 0;//為1表示升序,否則降序
    Ascending = a[1] > a[0] ? 1 : 0;
    int *CopyA = (int *)malloc(sizeof(int) * len);
    memset(CopyA, 0, sizeof(int) * len);
    //構建另一數組
    int icount = 0;
    for(icount = 0; icount < len; icount++)
    {
        CopyA[icount] = x - a[icount];
    }
    //比較兩個指針移動的值,這里用索引代替指針
    int i = len - 1, j = 0;
    while(i >= 0 && j < len)
    {
        if(a[i] > CopyA[j])
        {
            switch(Ascending)
            {
                case 0: j++; break;//降序
                case 1: i--; break;//升序
                default:break;
            }
        }
        else if(a[i] == CopyA[j] && i != j)
        {
            return 1;
        }
        else
        {
            switch(Ascending)
            {
                case 0: i--; break;//降序
                case 1: j++; break;//升序
                default:break;
            }
        }
    }
    return 0;
}
int main()
{
    int a[] = {1, 2, 3, 4};
    int len = 4;
    int x = 8;
    switch(Judge(a, len, x))
    {
        case 0: printf("%d isn't exist!", x);break;
        case 1: printf("%d is exist!", x);break;
        default : break;
    }
    return 0;
}
View Code

 

 2、給定有n個數的數組a,其中超過一半的數為一個定值,在不進行排序、不開設額外數組的情況下,以最高效的算法找到這個數:int find(int *a, int n)

解:審題發現,要求條件蠻多的:不進行排序,不開設額外數組。這道題目其實我沒有想到十分有效的方法,題解參考的編程之美2.3尋找發帖“水王”

算法的思想是:既然在數組中某個定值出現的次數超過一半,那么每次從數組中刪除兩個不同的數字,直到數組中的元素全部相同為止,最后剩下的數組相同的元素一定就是這個定值,這里使用一個計數器cnt,對數組中某個數VeryNum進行計數,通過計數器的加減來找到該定值。

算法流程圖:

 

code:

#include <stdio.h>
#include <stdlib.h>
int find(int *a, int n)
{
    int VeryNum = 0;
    int cnt = 0;
    int i = 0;
    for(i = 0; i < n; i++)
    {
        if(cnt == 0)
        {
            VeryNum = a[i];
            cnt = 1;
        }
        else
        {
            if(a[i] == VeryNum)
            {
                cnt++;
            }
            else
            {
                cnt--;
            }
        }
    }
    return VeryNum;
}
int main(void)
{
    int a[] = {15, 15, 5, 15, 5, 15, 1};
    int n = 7;
    printf("%d\n", find(a, n));
    return 0;
}
View Code

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM