天天看點

騰訊、百度、阿裡、微軟面試題精選(不斷更新)

1、for(i=0;i<10;++i,sum+=i);  循環結束時 i 和sum的值分别是多少?

  分析:循環結束時 i=10應該沒有問題,sum計算的位置不是很常見,每次sum+=i 時,i 的值都是先自加1,即 i(從0到9),計算sum時是從1加到10,結果55;

如果是:for(i=0;i<10;++i)  sum+=i;  循環結束時 i 和sum的值分别是多少?

  這次 i 依然是10,但是sum就是0到9的加和,結果45。

2、請定義一個宏,比較兩個數a、b的大小,不能使用大于、小于、if語句。

  #define Max(a,b) ((a-b)&(0x80))? b:a

  #define Max(a,b) ((a-b)&(1<<31))? b:a  兩種寫法是等價的。

注意:#define Max(a,b) (a/b)?a:b  這個答案是不全面的,隻适用于正整數。

3、不使用額外空間,将 A,B兩連結清單的元素交叉歸并。

  代碼使用了遞歸的方式實作合并兩個連結清單:

1 #include <iostream>
 2 using namespace std;
 3 
 4 typedef struct node
 5 {
 6     int val;
 7     struct node *next;
 8 }node;
 9 
10 node* createList(int n)
11 {
12     node *head;
13     node *pHead;//永遠指向最新的節點
14     node *pNext;//指向新添加的節點
15     for(int i=0;i<n;i++)
16     {
17         if(i==0)
18         {
19             head=new node;
20             cout<<"請輸入第1個元素(頭結點)的值:";
21             cin>>head->val;
22             head->next=NULL;
23             pHead=head;
24         }
25         else
26         {
27             pNext=new node;
28             cout<<"請輸入第"<<i+1<<"個元素的值:";
29             cin>>pNext->val;
30             pNext->next=NULL;
31             pHead->next=pNext;
32             pHead=pNext;
33         }
34     }
35     return head;
36 }
37 
38 void mergeTwoList(node *headA,node *headB)//headA的長度大于等于headB的
39 {
40     if(headA==NULL||headB==NULL)
41     {
42         return;
43     }
44     mergeTwoList(headA->next,headB->next);//遞歸實作
45     headB->next=headA->next;
46     headA->next=headB;
47 }
48 
49 int main()
50 {
51     node *headA;
52     node *headB;
53     node *newList;
54     cout<<"建立連結清單A:\n";
55     headA=createList(5);
56     cout<<"建立連結清單B:\n";
57     headB=createList(3);
58     newList=headA;
59     mergeTwoList(headA,headB);
60     cout<<"合并後的新連結清單:"<<endl;
61     while(newList!=NULL)
62     {
63         cout<<newList->val<<" ";
64         newList=newList->next;
65     }
66     return 0;
67 }      

4、*p=NULL *p=new char[100]  sizeof(p)各為多少?(一般都指的32位計算機)隻要是指針變量都是4位元組的,也就是計算機尋址空間是0到(2^32-1),即32位。

5、C語言中的記憶體洩漏:

動态記憶體的意思是程式運作時在堆上申請的記憶體。

而靜态記憶體是程式編譯時,在靜态存儲區申請的記憶體。

動态記憶體洩露指的是程式運作時,使用的new malloc realloc等函數沒有與之比對的delete free等函數。

造成程式不斷的同作業系統申請記憶體,而又不還給作業系統,申請的多了,作業系統本身也就沒記憶體可用了。

而應用程式,一旦退出,那麼作業系統是會自動回收該應用程式所在程序的全部資源的,是以,洩露的記憶體也就會被作業系統全部回收。

應用程式的記憶體分為四塊:堆區,棧區,全局資料區,代碼區  
其中堆區需要程式員自己管理,我們申請的動态變量就存放在堆區,用完後需要程式員自己手動釋放。
若申請了一塊動态記憶體,未釋放,卻丢失了指向性,這就叫記憶體洩露,會導緻程式的可用記憶體減少,嚴重的話會拖垮作業系統。      

6、

32位機上根據下面的代碼,問哪些說法是正确的?()

    signed char a = 0xe0;
    unsigned int b = a;
    unsigned char c = a;

    A. a>0 && c>0 為真 
    B. a == c 為真 
    C. b 的十六進制表示是:0xffffffe0 
    D.上面都不對      

有符号數和無符号數之間的轉換:c

首先,a=1110 0000,首位是1,signed是有符号數,是以是負的;unsigned int 是4個位元組的,無符号數,把a轉換成b時,負數前面補1,正數補0,是以b的16進制表示0xffffffe0;

  c是無符号數,單位元組的,c=0xe0,是正數。

轉一篇很好的部落格,看了就懂了:

#include <stdio.h>
int main(int argc, char *argv[])
{
    unsigned char a = -1;
char b = a;
    printf("%d  %d",a,b);

return 0;
}      
//結果:255  -1      
#include <stdio.h>
int main(int argc, char *argv[])
{
    unsigned short a = -1;
short b = a;
    printf("%d  %d",a,b);

return 0;
}
//結果:65535  -1      

這是兩段很簡單的代碼,我就以第二段代碼為例。

     在計算機中,負數是以補碼來存儲的。  轉載請注明出處http://www.cnblogs.com/stonehat/archive/2011/10/14/2212141.html

      C語言中常量整數 -1的補碼表示為0xFFFFFFFF。截取後面16位FFFF指派給 變量a(unsigned short)。此時 a = 0xFFFF(a沒有符号位,0xFFFF轉換為十進制為65535)。

      a又将0xFFFF,直接指派給short b。 此時 b = 0xFFFF(但是要注意,b是有符号的,0xFFFF轉換為十進制為-1)。

執行printf("%d %d",a,b);的時候,要将 a和b的值先轉換為int型:(這裡是重點!!!)

 a沒有符号是以轉為int型為0x0000FFFF,

 b有符号轉換為int型為0xFFFFFFFF。

十進制輸出值 65535  -1.   轉載請注明出處http://www.cnblogs.com/stonehat/archive/2011/10/14/2212141.html

#include <stdio.h>
int main(int argc, char *argv[])
{

    unsigned int a = -1;
int b = a;
    printf("%d  %d",a,b);

return 0;
}
//結果 -1 -1      

轉載請注明出處http://www.cnblogs.com/stonehat/archive/2011/10/14/2212141.html

a在記憶體中值為0xFFFFFFFF,b的值為0xFFFFFFFF,都已經32位,

a轉換為int型的時候就是0xFFFFFFFF,是以輸出-1.

其實,記住兩點就行了

1.unsigned 類型轉換為 signed類型的時候是直接複制到低位,高位為0.如果signed類型位數不夠,隻直接裝載unsigned低位。

2.signed類型轉換為unsigned類型的時候,也是将補碼直接複制到低位,高位為符号位。如果unsigned位數不夠,隻直接裝載signed低位。

7、

1 下面哪些選項能編譯通過?  
 2 int i;
 3 char a[10]; 
 4 string f(); 
 5 string g(string &str);  
 6 
 7 A. if(!!i){f();} 
 8 B. g(f()); 
 9 C. a=a+1; 
10 D. g("abc");       

解析:c、c++會給未初始化的變量随機指派,是以A是可以的;B是錯誤的,因為一個函數的傳回值是一個臨時變量,g函數參數是一個引用變量,應該傳入一個定義好的變量作為參數,例如 string a="abc";g(a);是以D也是錯誤的,如果是g(string str)函數,B、D都是對的。C是錯的,因為a是指向數組a[10]的首位址的指針,是個常量,不能指派的,就像5=5+1是不可能的。但是 char *p; p=a;p++;這就可以了,因為p是變量了。

8、

問下面的資料都存放在哪些存儲區?

int main()
{
    char *p = "hello,world";
    return 0;
}

A. 堆和靜态資料區
B. 棧和靜态資料區
C. 棧和常量區
D. 棧和堆      

解析:根據C語言中的特性和定義p是一個局部變量,而C語言中局部變量存在于棧中,"hello wrold"是一個字元串常量,是以存儲于程式的隻讀存儲區中,p在這裡其實隻是指向了"hello wrold"在隻讀存儲區中的位址而已。

12、問題:在一個二維數組中,每行的元素從左到右是遞增的,每列元素從上到下是遞增的。寫一個函數,查找一給定的元素是否在此數組中

輸入:一個二維數組,和一個待查找的數

輸出:待查找的數在數組中輸出“YES",否則輸出”NO"

原始思路:最簡單思路就是暴力搜尋,周遊一遍數組中的元素時間複雜度為O(n2)。但是這樣就沒有用問題的已知條件(從左到右、從上到下遞增),是以不是個好的解法

改進1:從第一行開始找,找到待查元素大的,如果還沒找到,接着從第二行開始找,直到找到或到最後一個元素為止(如圖),但是如果帶查找的元素在最後,還得周遊到最後,時間複雜度還是O(n2)

騰訊、百度、阿裡、微軟面試題精選(不斷更新)

改進2:上來在随機在裡面挑一個,如果正好逮住,那就結束了;如果比待查找的元素大,那麼他的左邊和上邊;否則在右邊和下邊。如下圖。這樣下來可以減少一部分元素的比較。在尋找1時,會話費反而很多時間,并不是個好的解決辦法。

騰訊、百度、阿裡、微軟面試題精選(不斷更新)

改進3:看兩個比較關鍵的兩個點——左下角和右上角。以右上角為例(如下圖)。如果右上角元素等于帶查找元素,那就傳回真;如果右上角元素大于待查找元素,那就删除右上角元素所在列;否則删除其所在行。依次進行下去。

騰訊、百度、阿裡、微軟面試題精選(不斷更新)

舉例說明:

騰訊、百度、阿裡、微軟面試題精選(不斷更新)

參考代碼一:

#include <stdio.h>

int find_value(int a[][4], int value, int x, int y)//(x,y)表示右上角坐标
{
    if ((x >= 0) && (y < 4))
    {
        if (a[x][y] ==  value)
            return 1;
        else if (a[x][y] > value)
            return find_value(a, value, x-1, y);
        else
            return find_value(a, value, x, y+1);
    }

    return 0;
}

int main()
{
    int a[4][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
    int val;
    printf("Enter your number:");
    scanf("%d", &val);
    if(find_value(a, val, 3, 0))
        printf("Yes, find it\n");
    else
        printf("No, not find it\n");

    return 0;
}
      

轉載于:https://www.cnblogs.com/nannanITeye/archive/2013/04/07/3005999.html

繼續閱讀