2013網易實習生招聘筆試題


選擇題:

1、二維數組int a[3][4],下列能表示a[1][2]的是?

A.*(*(a+1)+2)    B.*(a+3)    C.(&a[0]+1)[2]    D.(a[0]+1)

2、short a[100],則sizeof(a)的值是?

A.2     B.4    C.200    D.400

問答題:

1、解釋說明static、const和volatile兩個關鍵字的作用?

關鍵字static有三個明顯的作用:
1、在函數體,一個被聲明為靜態的變量在這一函數被調用過程中維持其值不變。
2、 在模塊內(但在函數體外),一個被聲明為靜態的變量可以被模塊內所有函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變量。
3、在模塊內,一個被聲明為靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地范圍內使用。

const 有什么用途?
1、可以定義 const 常量
2、const可以修飾函數的參數、返回值,甚至函數的定義體。被const修飾的東西都受到強制保護,可以預防意外的變動,能提高程序的健壯性。

volatile問題:

volatile的作用: 作為指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值。。。
volatile的語法與const是一樣的,但是volatile的意思是“在編譯器認識的范圍外,這個數據可以被改變”。不知何故,環境正在改變數據(可能通過多任務處理),所以,volatile告訴編譯器不要擅自作出有關數據的任何假設——在優化起家這是特別重要的。如果編譯器說:“我已經把數據讀入寄存器,而且在沒有與寄存器接觸。”在一般情況下,它不需要再讀入這個數據。但是,如果數據是volatile修飾的,編譯器則是不能做出這樣的假定,因為數據可能被其他進程改變了,編譯器必須重新讀這個數據而不是優化這個代碼。就像建立const對象一樣,程序員也可以建立volatile對象,甚至還建立const volatile對象。這個對象不能被程序員改變,但可通過外面的工具改變。
volatile對象每次被訪問時必須重新讀取這個變量的值,而不是用保存在寄存器中的備份。下面時volatile變量的幾個例子:
.並行設備的硬件寄存器(如狀態寄存器);
.一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables);
.多現成應用中被幾個任務共享的變量。
一個參數可以const同時也是volatile,一個指針也是可以為volatile的,但是具體編程時要小心,要保證不被意外修改。

1、static關鍵字的作用,個人經驗主要有以下幾種:1)函數局部static變量,第一次函數調用被初始化,后續每次調用將使用上次調用后保存的值;2)全局變量中static變量,可以防止被其他文件的代碼使用這個變量,有點將這個全局變量設置為private的意味;3)對於static函數來說,效果和2中的變量相同;4)C++類中static方法,不需要實例化訪問;5)C++定義static類成員變量,不需要實例化訪問,不過需要先定義,定義的時候可以初始化數組。

2、volatile用來聲明一個變量,並強制程序在每次使用變量的重新從變量地址讀取數據,這是為了防止變量在其他地方被改變,而程序仍然使用沒有更新的數據。

 2、說明C++內存分配方式有幾種?每種使用都有哪些注意項?

1.從靜態存儲區域分配內存在程序編譯時候就已經分配好,這塊內存在程序整個運行期間都存在。例如全局變量,static變量。   
2.在棧上創建。在執行函數時,函數內局部變量存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器指令集中,效率很高,但是分配內存容量有限。   
3.從堆上分配,亦稱動態內存分配程序在運行時候用malloc或new申請任意多少內存,程序員自己負責在何時用free或delete釋放內存。動態內存生存期由我們決定,使用非常靈活,但問題也最多。
----------------------------------------
一般所說堆棧(stack)往往是指棧,先進后出,它是一塊內存區。用以存放程序局部變量,臨時變量,函數參數,返回地址等。在這塊區域中變量分配和釋放由系統自動進行。不需要用戶參與。   
   而在堆(heap,先進先出)空間則是由用戶進行分配,並由用戶負責釋放

編程題:

1、給定一個升序排列的自然數數組,數組中包含重復數字,例如:[1,2,2,3,4,4,4,5,6,7,7]。問題:給定任意自然數,對數組進行二分查找,返回數組正確的位置,給出函數實現。注:連續相同的數字,返回第一個匹配位置還是最后一個匹配位置,由函數傳入參數決定。

分析:既然是二分查找的變形,那么先寫個正確的二分查找吧:

#include<iostream>
using namespace std;
int bin_search(int arr[],int n,int value)
{
    if(arr==NULL||n<1)
        return -1;
    int left=0;
    int right=n-1;
    while(left<=right)
    {
        int mid=left+((right-left)>>1);
        if(arr[mid]>value)
        {
            right=mid-1;
        }
        else if(arr[mid]<value)
        {
             left=mid+1;
        }
        else
            return mid;
    }
    return -1;
}
int main()
{
    int arr[]={1,2,3,4,5,6,7,8,9};
    int b=bin_search(arr,9,9);
    cout<<b<<endl;
    system("pause");
    return 0;
}

代碼如下:

/*
* 測試樣例
* 11
* 1 2 2 3 4 4 4 5 7 7 7
*/
#include<stdio.h>
#include<stdlib.h>
#define MAX 20
int n;
int sets[MAX];
enum MATCH_POS{PRE,POST};//分別為第一個匹配和最后一個匹配

int bi_search(int *arr,int b,int e,int v,MATCH_POS pos)
{
    int left,right,mid;
    left=b-1;right=e;
    while(left+1 < right)
    {
        mid=left+(right - left)/2;
        if(v < arr[mid])
        {
            right = mid;
        }else if(v > arr[mid])
        {
            left=mid;
        }else
        {
            if(pos==PRE)
            {//如尋找第一個匹配,right向左移動
                right = mid;
            }
            else
                left = mid;
        }
    }
    if(arr[right] == v)
        return right;
    else if(arr[left] == v)
        return left;
    return -1;
}

int main(){
    int i;
    int sets[]={1, 2, 2, 3, 4, 4, 4, 5, 7, 7, 7};
    int t=bi_search(sets,0,10,7,PRE);
    printf("%d\n",t);
    system("pause");
    return 0;
}

2、一個無序自然數數組,比如[100,2,1,3]求在0(n)時間復雜度內求出最大的連續自然數個數:輸出應該是3,要求算法的時間復雜度為O(n)
方法一:排序
可以采用一些排序方法比如基數排序、桶排序、記數排序等先進行排序。然后遍歷一遍所有元素即可。當前這些排序有一些限制條件的。

方法二:維持一個hash表
維持一個hash表,大小為最大整數。遍歷一次數組,用hash表記錄出現在原始數組中的數。
然后設置四個個指示變量start,end,length,bestLength = 0。初始,start = end = 數組中第一個數,length = 1。然后不斷執行下列操作:
end = end + 1.然后ziahash表中尋找end,如果能夠找到,說明end存在原始數組中。一直到找不到end位置。
然后設置length = end - start。如果length大於bestLength,則更新:bestLength = length。
然后將start和end都設置為剛才為查找到的那個數,length = 1,接着重復上面的操作,最終的bestLength 便是最大的連續自然數個數。
由於hash的查找等操作都能在O(1)時間復雜度內完成,因此hash方法能夠滿足O(n)時間復雜度。

方法三:位圖
用位圖。類似方法二。
位圖大小和最大的整數有關。位圖中每一位為0或者1。位圖某個位置index上為1表示index出現在原始數組中,反之不存在。遍歷一遍原始數組建立位圖之后,采用類似方法二中遍歷hash表的方法遍歷位圖,找出最大的連續自然數個數。
位圖的方法存在一個問題就是:可能最大的數很大,但是數的數目有很小,這時候要申請的位圖的空間依然是很大,時候復雜度不是O(n)。

方法四:維持兩個hash表

維持兩個hash表tables:
Start表,其中的條目都是如下格式(start-point,length),包含的某個連續序列起始數以及序列長度。
End表,其中的條目都是如下格式(end-point,length),包含的某個連續序列結束數以及序列長度。

掃描原始數組,做如下操作:
對於當前值value,
判斷value + 1是否存在於start表中。
如果存在,刪除相應的條目,創建一個新條目(value,length + 1),同時更新end表相應條目,結束數不變,該對應長度加一。
判斷value - 1是否存在於end表中。
如果存在,刪除相應的條目,創建一個新條目(value,length + 1),同時更新start表相應條目,開始數不表,該對應長度加一。
如果在兩個表中都存在,則合並兩個已經存在的連續序列為一個。將四個條目刪除,新建兩個條目,每兩個條目代表一個連續序列。
如果都不存在,則只需要在兩個表中創建一個新的長度為1的條目。

一直這樣等到數組中所有元素處理完畢,然后掃描start表尋找length值最大的那個即可。

這里要達到O(n)時間復雜度,start表和end表都用hash表實現,而且必須滿足相關操作查找/添加/刪除能夠在O(1)時間復雜度內完成。

實例分析:
int[] input = {10,21,45,22,7,2,67,19,13,45,12, 11,18,16,17,100,201,20,101};

初始化狀態:
Start table:{}
End table:{}
開始遍歷數組:
10:兩個數組中都不存在,添加條目。
Start table:{(10,1)}
End table:{(10,1)}
21:兩個數組中都不存在,添加條目。
Start table:{(10,1),(21,1)}
End table:{(10,1),(21,1)}
45:兩個數組中都不存在,添加條目。
Start table:{(10,1),(21,1),(45,1)}
End table:{(10,1),(21,1),(45,1)}
22:22-1=21存在於end表中需要進行更新。
Start table:{(10,1),(21,2),(45,1)}
End table:{(10,1),(22,2),(45,1)}
7:兩個數組中都不存在,添加條目。
Start table:{(10,1),(21,2),(45,1),(7,1)}
End table:{(10,1),(22,2),(45,1),(7,1)}
2:兩個數組中都不存在,添加條目。
Start table:{(10,1),(21,2),(45,1),(7,1),(2,1)}
End table:{(10,1),(22,2),(45,1),(7,1),(2,1)}
67:兩個數組中都不存在,添加條目。
Start table:{(10,1),(21,2),(45,1),(7,1),(2,1),(67,1)}
End table:{(10,1),(22,2),(45,1),(7,1),(2,1),(67,1)}
19:兩個數組中都不存在,添加條目。
Start table:{(10,1),(21,2),(45,1),(7,1),(2,1),(67,1),(19,1)}
End table:{(10,1),(22,2),(45,1),(7,1),(2,1),(67,1),(19,1)}
13:兩個數組中都不存在,添加條目。
Start table:{(10,1),(21,2),(45,1),(7,1),(2,1),(67,1),(19,1),(13,1)}
End table:{(10,1),(22,2),(45,1),(7,1),(2,1),(67,1),(19,1),(13,1)}
45:兩個數組中都不存在,添加條目。
Start table:{(10,1),(21,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,1),(13,1)}
End table:{(10,1),(22,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,1),(13,1)}
12:12+1=13存在start表中,更新。
Start table:{(10,1),(21,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,1),(12,2)}
End table:{(10,1),(22,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,1),(13,2)}
11:11+1=12都存在,合並。
Start table:{(10,4),(21,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,1)}
End table:{(13,4),(22,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,1)}
18:18+1=19存在start表中,更新。
Start table:{(10,4),(21,2),(45,1),(45,1),(7,1),(2,1),(67,1),(18,2)}
End table:{(13,4),(22,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,2)}
16:都不存在,添加條目。
Start table:{(10,4),(21,2),(45,1),(45,1),(7,1),(2,1),(67,1),(18,2),(16,1)}
End table:{(13,4),(22,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,2),(16,1)}
17:都存在,合並。
Start table:{(10,4),(21,2),(45,1),(45,1),(7,1),(2,1),(67,1),(16,4)}
End table:{(13,4),(22,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,4)}
100:都不存在,添加條目。
Start table:{(10,4),(21,2),(45,1),(45,1),(7,1),(2,1),(67,1),(16,4),(100,1)}
End table:{(13,4),(22,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,4),(100,1)}
201:都不存在,添加條目。
Start table:{(10,4),(21,2),(45,1),(45,1),(7,1),(2,1),(67,1),(16,4),(100,1),(201,1)}
End table:{(13,4),(22,2),(45,1),(45,1),(7,1),(2,1),(67,1),(19,4),(100,1),(201,1)}
20:都存在,合並。
Start table:{(10,4),(16,7),(45,1),(45,1),(7,1),(2,1),(67,1),(100,1),(201,1)}
End table:{(13,4),(22,7),(45,1),(45,1),(7,1),(2,1),(67,1),(100,1),(201,1)}
101:都存在,合並。
Start table:{(10,4),(16,7),(45,1),(45,1),(7,1),(2,1),(67,1),(100,1),(201,1),(101,1)}
End table:{(13,4),(22,7),(45,1),(45,1),(7,1),(2,1),(67,1),(100,1),(201,1),(201,1)}

最后搜索start表,找到length值最大的,為7.連續自然數序列是:(16,17,18,19,20,21,22).
結束。

 

#include <stdio.h>

int array[]={100, 2, 1, 3, 8, 5, 4};
int size = sizeof(array) / sizeof(int);

//構造兩個簡陋的hash表,一個是用來查詢數字是否存在,一個用於標記數字是否使用過
char hash_exist[1024];
char hash_used[1024];

int main()
{
    int i, j, n, max = 0, maxnum = array[0], minnum = array[0];
    for(i = 0; i < size; i++)
    {
        //標記數字存在
        hash_exist[array[i]] = 1;
        //找出數組最大元素
        if(maxnum < array[i]) maxnum = array[i];
        //找出數組最小元素
        if(minnum > array[i]) minnum = array[i];
    }
    for(i = 0; i < size; i++)
    {
        j = array[i];
        //如果已經統計過,就跳過
        if(hash_used[j])
            continue;
        //標記本身
        n = 1;
        hash_used[j] = 1;
        //比array[i]大的連續元素統計
        while(++j <= maxnum)
        {
            if(hash_exist[j])
            {
                n++;
                hash_used[j] = 1;
            }
            else
                break;
        }
        //比array[i]小的連續元素統計
        j = array[i];
        while(--j >= minnum)
        {
            if(hash_exist[j])
            {
                n++;
                hash_used[j] = 1;
            }
            else
                break;
        }
        //更新最大連續數字
        if(n > max) max = n;
    }
    printf("%d\n", max);
    return 0;
}

 


免責聲明!

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



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