溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

常見的Java中數(shù)據(jù)結(jié)構(gòu)面試題

發(fā)布時(shí)間:2020-12-04 15:39:35 來源:億速云 閱讀:196 作者:Leah 欄目:編程語言

常見的Java中數(shù)據(jù)結(jié)構(gòu)面試題?針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡單易行的方法。

1.棧和隊(duì)列的共同特點(diǎn)是(只允許在端點(diǎn)處插入和刪除元素)
4.棧通常采用的兩種存儲(chǔ)結(jié)構(gòu)是(線性存儲(chǔ)結(jié)構(gòu)和鏈表存儲(chǔ)結(jié)構(gòu))
5.下列關(guān)于棧的敘述正確的是(D)
     A.棧是非線性結(jié)構(gòu)B.棧是一種樹狀結(jié)構(gòu)C.棧具有先進(jìn)先出的特征D.棧有后進(jìn)先出的特征
6.鏈表不具有的特點(diǎn)是(B)A.不必事先估計(jì)存儲(chǔ)空間       B.可隨機(jī)訪問任一元素
C.插入刪除不需要移動(dòng)元素      D.所需空間與線性表長度成正比
7.用鏈表表示線性表的優(yōu)點(diǎn)是(便于插入和刪除操作)
8.在單鏈表中,增加頭結(jié)點(diǎn)的目的是(方便運(yùn)算的實(shí)現(xiàn))
9.循環(huán)鏈表的主要優(yōu)點(diǎn)是(從表中任一結(jié)點(diǎn)出發(fā)都能訪問到整個(gè)鏈表)
10.線性表L=(a1,a2,a3,……ai,……an),下列說法正確的是(D)
     A.每個(gè)元素都有一個(gè)直接前件和直接后件   B.線性表中至少要有一個(gè)元素
     C.表中諸元素的排列順序必須是由小到大或由大到小
     D.除第一個(gè)和最后一個(gè)元素外,其余每個(gè)元素都有一個(gè)且只有一個(gè)直接前件和直接后件
11.線性表若采用鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)時(shí),要求內(nèi)存中可用存儲(chǔ)單元的地址(D)
A.必須是連續(xù)的 B.部分地址必須是連續(xù)的C.一定是不連續(xù)的 D.連續(xù)不連續(xù)都可以
12.線性表的順序存儲(chǔ)結(jié)構(gòu)和線性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)分別是(隨機(jī)存取的存儲(chǔ)結(jié)構(gòu)、順序存取的存儲(chǔ)結(jié)構(gòu))
13.樹是結(jié)點(diǎn)的集合,它的根結(jié)點(diǎn)數(shù)目是(有且只有1)
14.在深度為5的滿二叉樹中,葉子結(jié)點(diǎn)的個(gè)數(shù)為(31)
15.具有3個(gè)結(jié)點(diǎn)的二叉樹有(5種形態(tài))
16.設(shè)一棵二叉樹中有3個(gè)葉子結(jié)點(diǎn),有8個(gè)度為1的結(jié)點(diǎn),則該二叉樹中總的結(jié)點(diǎn)數(shù)為(13)
17.已知二叉樹后序遍歷序列是dabec,中序遍歷序列是debac,它的前序遍歷序列是(cedba)
18.已知一棵二叉樹前序遍歷和中序遍歷分別為ABDEGCFH和DBGEACHF,則該二叉樹的后序遍歷為(DGEBHFCA)
19.若某二叉樹的前序遍歷訪問順序是abdgcefh,中序遍歷訪問順序是dgbaechf,則其后序遍歷的結(jié)點(diǎn)訪問順序是(gdbehfca)
20.數(shù)據(jù)庫保護(hù)分為:安全性控制、完整性控制、并發(fā)性控制和數(shù)據(jù)的恢復(fù)。

1. 在計(jì)算機(jī)中,算法是指(解題方案的準(zhǔn)確而完整的描述)
2.在下列選項(xiàng)中,哪個(gè)不是一個(gè)算法一般應(yīng)該具有的基本特征(無窮性)
說明:算法的四個(gè)基本特征是:可行性、確定性、有窮性和擁有足夠的情報(bào)。
3. 算法一般都可以用哪幾種控制結(jié)構(gòu)組合而成(順序、選擇、循環(huán))
4.算法的時(shí)間復(fù)雜度是指(算法執(zhí)行過程中所需要的基本運(yùn)算次數(shù))
5. 算法的空間復(fù)雜度是指(執(zhí)行過程中所需要的存儲(chǔ)空間)     
6. 算法分析的目的是(分析算法的效率以求改進(jìn))     
7. 下列敘述正確的是(C)
A.算法的執(zhí)行效率與數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)無關(guān)
B.算法的空間復(fù)雜度是指算法程序中指令(或語句)的條數(shù)
C.算法的有窮性是指算法必須能在執(zhí)行有限個(gè)步驟之后終止
D.算法的時(shí)間復(fù)雜度是指執(zhí)行算法程序所需要的時(shí)間
8.數(shù)據(jù)結(jié)構(gòu)作為計(jì)算機(jī)的一門學(xué)科,主要研究數(shù)據(jù)的邏輯結(jié)構(gòu)、對(duì)各種數(shù)據(jù)結(jié)構(gòu)進(jìn)行的運(yùn)算,以及(數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu))
9. 數(shù)據(jù)結(jié)構(gòu)中,與所使用的計(jì)算機(jī)無關(guān)的是數(shù)據(jù)的(C)
A.存儲(chǔ)結(jié)構(gòu)   B.物理結(jié)構(gòu)     C.邏輯結(jié)構(gòu)     D.物理和存儲(chǔ)結(jié)構(gòu)
10. 下列敘述中,錯(cuò)誤的是(B)
A.?dāng)?shù)據(jù)的存儲(chǔ)結(jié)構(gòu)與數(shù)據(jù)處理的效率密切相關(guān)
B.?dāng)?shù)據(jù)的存儲(chǔ)結(jié)構(gòu)與數(shù)據(jù)處理的效率無關(guān)
C.?dāng)?shù)據(jù)的存儲(chǔ)結(jié)構(gòu)在計(jì)算機(jī)中所占的空間不一定是連續(xù)的
D.一種數(shù)據(jù)的邏輯結(jié)構(gòu)可以有多種存儲(chǔ)結(jié)構(gòu)
11. 數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)是指(數(shù)據(jù)的邏輯結(jié)構(gòu)在計(jì)算機(jī)中的表示)
12. 數(shù)據(jù)的邏輯結(jié)構(gòu)是指(反映數(shù)據(jù)元素之間邏輯關(guān)系的數(shù)據(jù)結(jié)構(gòu))
13. 根據(jù)數(shù)據(jù)結(jié)構(gòu)中各數(shù)據(jù)元素之間前后件關(guān)系的復(fù)雜程度,一般將數(shù)據(jù)結(jié)構(gòu)分為(線性結(jié)構(gòu)和非線性結(jié)構(gòu))
14. 下列數(shù)據(jù)結(jié)構(gòu)具有記憶功能的是(C)A.隊(duì)列B.循環(huán)隊(duì)列C.棧D.順序表
15. 下列數(shù)據(jù)結(jié)構(gòu)中,按先進(jìn)后出原則組織數(shù)據(jù)的是(B)
A.線性鏈表   B.棧            C.循環(huán)鏈表        D.順序表
16. 遞歸算法一般需要利用(隊(duì)列)實(shí)現(xiàn)。
17. 下列關(guān)于棧的敘述中正確的是(D)A.在棧中只能插入數(shù)據(jù)B.在棧中只能刪除數(shù)據(jù)
C.棧是先進(jìn)先出的線性表            D.棧是先進(jìn)后出的線性表
20. 由兩個(gè)棧共享一個(gè)存儲(chǔ)空間的好處是(節(jié)省存儲(chǔ)空間,降低上溢發(fā)生的機(jī)率)

21. 應(yīng)用程序在執(zhí)行過程中,需要通過打印機(jī)輸出數(shù)據(jù)時(shí),一般先形成一個(gè)打印作業(yè),將其存放在硬盤中的一個(gè)指定(隊(duì)列)中,當(dāng)打印機(jī)空閑時(shí),就會(huì)按先來先服務(wù)的方式從中取出待打印的作業(yè)進(jìn)行打印。
22.下列關(guān)于隊(duì)列的敘述中正確的是(C)A.在隊(duì)列中只能插入數(shù)據(jù) B.在隊(duì)列中只能刪除數(shù)據(jù)   C.隊(duì)列是先進(jìn)先出的線性表            D.隊(duì)列是先進(jìn)后出的線性表
23.下列敘述中,正確的是(D)A.線性鏈表中的各元素在存儲(chǔ)空間中的位置必須是連續(xù)的
B.線性鏈表中的表頭元素一定存儲(chǔ)在其他元素的前面 C.線性鏈表中的各元素在存儲(chǔ)空間中的位置不一定是連續(xù)的,但表頭元素一定存儲(chǔ)在其他元素的前面 D.線性鏈表中的各元素在存儲(chǔ)空間中的位置不一定是連續(xù)的,且各元素的存儲(chǔ)順序也是任意的
24.下列敘述中正確的是(A)A.線性表是線性結(jié)構(gòu)      B.棧與隊(duì)列是非線性結(jié)構(gòu)
C.線性鏈表是非線性結(jié)構(gòu)                                 D.二叉樹是線性結(jié)構(gòu)
25. 線性表L=(a1,a2,a3,……ai,……an),下列說法正確的是(D)
A.每個(gè)元素都有一個(gè)直接前件和直接后件      B.線性表中至少要有一個(gè)元素
C.表中諸元素的排列順序必須是由小到大或由大到小D.除第一個(gè)元素和最后一個(gè)元素外,其余每個(gè)元素都有一個(gè)且只有一個(gè)直接前件和直接后件
26.線性表若采用鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)時(shí),要求內(nèi)存中可用存儲(chǔ)單元的地址(連續(xù)不連續(xù)都可以)     
27. 鏈表不具有的特點(diǎn)是(B)A.不必事先估計(jì)存儲(chǔ)空間            B.可隨機(jī)訪問任一元素
C.插入刪除不需要移動(dòng)元素            D.所需空間與線性表長度成正比
28. 非空的循環(huán)單鏈表head的尾結(jié)點(diǎn)(由p所指向),滿足(p->next=head)
29.與單向鏈表相比,雙向鏈表的優(yōu)點(diǎn)之一是(更容易訪問相鄰結(jié)點(diǎn))     
30. 在(D)中,只要指出表中任何一個(gè)結(jié)點(diǎn)的位置,就可以從它出發(fā)依次訪問到表中其他所有結(jié)點(diǎn)。A.線性單鏈表            B.雙向鏈表            C.線性鏈表            D.循環(huán)鏈表
31. 以下數(shù)據(jù)結(jié)構(gòu)屬于非線性數(shù)據(jù)結(jié)構(gòu)的是(C)A.隊(duì)列      B.線性表C.二叉樹      D.棧
32.樹是結(jié)點(diǎn)的集合,它的根結(jié)點(diǎn)數(shù)目是(有且只有1)
33.具有3個(gè)結(jié)點(diǎn)的二叉樹有(5種形態(tài))     
34. 在一棵二叉樹上第8層的結(jié)點(diǎn)數(shù)最多是(128)注:2K-1
35. 在深度為5的滿二叉樹中,葉子結(jié)點(diǎn)的個(gè)數(shù)為(16)注:2n-1
36. 在深度為5的滿二叉樹中,共有(31)個(gè)結(jié)點(diǎn)。注:2n-1
37.設(shè)一棵完全二叉樹共有699個(gè)結(jié)點(diǎn),則在該二叉樹中的葉子結(jié)點(diǎn)數(shù)為(350)
說明:完全二叉樹總結(jié)點(diǎn)數(shù)為N,若N為奇數(shù),則葉子結(jié)點(diǎn)數(shù)為(N+1)/2;若N為偶數(shù),則葉子結(jié)點(diǎn)數(shù)為N/2。
38. 設(shè)有下列二叉樹,對(duì)此二叉樹中序遍歷的結(jié)果是(B)
A.ABCDEF     
B.DBEAFC
C.ABDECF     
D.DEBFCA
39.已知二叉樹后序遍歷序列是dabec,中序遍歷序列debac,它的前序遍歷序列是(cedba)     
40. 已知一棵二叉樹前序遍歷和中序遍歷分別為ABDEGCFH和DBGEACHF,則該二叉樹的后序遍歷為(DGEBHFCA)

41.若某二叉樹的前序遍歷訪問順序是abdgcefh,中序遍歷訪問順序是dgbaechf,則其后序遍歷的結(jié)點(diǎn)訪問順序是(gdbehfca)
42. 串的長度是(串中所含字符的個(gè)數(shù))     
43.設(shè)有兩個(gè)串p和q,求q在p中首次出現(xiàn)位置的運(yùn)算稱做(模式匹配)
44. N個(gè)頂點(diǎn)的連通圖中邊的條數(shù)至少為(N-1)
45.N個(gè)頂點(diǎn)的強(qiáng)連通圖的邊數(shù)至少有(N)
46.對(duì)長度為n的線性表進(jìn)行順序查找,在最壞情況下所需要的比較次數(shù)為(N)
47. 最簡單的交換排序方法是(冒泡排序)     
48.假設(shè)線性表的長度為n,則在最壞情況下,冒泡排序需要的比較次數(shù)為(n(n-1)/2)     
49. 在待排序的元素序列基本有序的前提下,效率最高的排序方法是(冒泡排序)
50. 在最壞情況下,下列順序方法中時(shí)間復(fù)雜度最小的是(堆排序)     
51. 希爾排序法屬于(插入類排序)
52. 堆排序法屬于(選擇類排序)
53. 在下列幾種排序方法中,要求內(nèi)存量最大的是(歸并排序)     
54. 已知數(shù)據(jù)表A中每個(gè)元素距其最終位置不遠(yuǎn),為節(jié)省時(shí)間,應(yīng)采用(直接插入排序)
55. 算法的基本特征是可行性、確定性、有窮性   和擁有足夠的情報(bào)。

1.一個(gè)算法通常由兩種基本要素組成:一是對(duì)數(shù)據(jù)對(duì)象的運(yùn)算和操作,二是算法的控制結(jié)構(gòu)。
1. 算法的復(fù)雜度主要包括時(shí)間復(fù)雜度和空間復(fù)雜度。
2. 實(shí)現(xiàn)算法所需的存儲(chǔ)單元多少和算法的工作量大小分別稱為算法的空間復(fù)雜度和時(shí)間復(fù)雜度。
3.所謂數(shù)據(jù)處理是指對(duì)數(shù)據(jù)集合中的各元素以各種方式進(jìn)行運(yùn)算,包括插入、刪除、查找、更改等運(yùn)算,也包括對(duì)數(shù)據(jù)元素進(jìn)行分析。
4.數(shù)據(jù)結(jié)構(gòu)是指相互有關(guān)聯(lián)的數(shù)據(jù)元素的集合。
5.數(shù)據(jù)結(jié)構(gòu)分為邏輯結(jié)構(gòu)與存儲(chǔ)結(jié)構(gòu),線性鏈表屬于存儲(chǔ)結(jié)構(gòu)。
6.數(shù)據(jù)結(jié)構(gòu)包括數(shù)據(jù)的邏輯結(jié)構(gòu)和數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)。
7. 數(shù)據(jù)結(jié)構(gòu)包括數(shù)據(jù)的邏輯結(jié)構(gòu)、數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)以及對(duì)數(shù)據(jù)的操作運(yùn)算。
8.數(shù)據(jù)元素之間的任何關(guān)系都可以用前趨和后繼關(guān)系來描述。
9.數(shù)據(jù)的邏輯結(jié)構(gòu)有線性結(jié)構(gòu)和非線性結(jié)構(gòu)兩大類。
10.常用的存儲(chǔ)結(jié)構(gòu)有順序、鏈接、索引等存儲(chǔ)結(jié)構(gòu)。
11. 順序存儲(chǔ)方法是把邏輯上相鄰的結(jié)點(diǎn)存儲(chǔ)在物理位置   相鄰的存儲(chǔ)單元中。
12. 棧的基本運(yùn)算有三種:入棧、退棧與讀棧頂元素。
13. 隊(duì)列主要有兩種基本運(yùn)算:入隊(duì)運(yùn)算與退隊(duì)運(yùn)算。
14. 在實(shí)際應(yīng)用中,帶鏈的??梢杂脕硎占?jì)算機(jī)存儲(chǔ)空間中所有空閑的存儲(chǔ)結(jié)點(diǎn),這種帶鏈的棧稱為可利用棧。
15.棧和隊(duì)列通常采用的存儲(chǔ)結(jié)構(gòu)是鏈?zhǔn)酱鎯?chǔ)和順序存儲(chǔ)   。
16.當(dāng)線性表采用順序存儲(chǔ)結(jié)構(gòu)實(shí)現(xiàn)存儲(chǔ)時(shí),其主要特點(diǎn)是邏輯結(jié)構(gòu)中相鄰的結(jié)點(diǎn)在存儲(chǔ)結(jié)構(gòu)中仍相鄰。
17. 循環(huán)隊(duì)列主要有兩種基本運(yùn)算:入隊(duì)運(yùn)算與退隊(duì)運(yùn)算。每進(jìn)行一次入隊(duì)運(yùn)算,隊(duì)尾指針就進(jìn)1 。
18.當(dāng)循環(huán)隊(duì)列非空且隊(duì)尾指針等于對(duì)頭指針時(shí),說明循環(huán)隊(duì)列已滿,不能進(jìn)行入隊(duì)運(yùn)算。這種情況稱為上溢   。
19.當(dāng)循環(huán)隊(duì)列為空時(shí),不能進(jìn)行退隊(duì)運(yùn)算,這種情況稱為下溢。
20. 在一個(gè)容量為25的循環(huán)隊(duì)列中,若頭指針front=16,尾指針rear=9,則該循環(huán)隊(duì)列中共有 18 個(gè)元素。注:當(dāng)rear<front時(shí),元素個(gè)數(shù)=總?cè)萘浚╢ront-rear);
當(dāng)rear>front時(shí),元素個(gè)數(shù)=rear-front。

1.判斷鏈表是否存在環(huán)型鏈表問題:判斷一個(gè)鏈表是否存在環(huán),例如下面這個(gè)鏈表就存在一個(gè)環(huán):
例如N1->N2->N3->N4->N5->N2就是一個(gè)有環(huán)的鏈表,環(huán)的開始結(jié)點(diǎn)是N5這里有一個(gè)比較簡單的解法。設(shè)置兩個(gè)指針p1,p2。每次循環(huán)p1向前走一步,p2向前走兩步。直到p2碰到NULL指針或者兩個(gè)指針相等結(jié)束循環(huán)。如果兩個(gè)指針相等則說明存在環(huán)。

struct link 
{
 int data;
  link* next;
};
bool IsLoop(link* head)
{
  link* p1=head, *p2 = head;
  if (head ==NULL || head->next ==NULL) 
  {
   return false;
  }
  do{
  p1= p1->next;
  p2 = p2->next->next;
  } while(p2 && p2->next && p1!=p2);  
  if(p1 == p2)
   return true;
  else
   return false;
}

2,鏈表反轉(zhuǎn)單向鏈表的反轉(zhuǎn)是一個(gè)經(jīng)常被問到的一個(gè)面試題,也是一個(gè)非?;A(chǔ)的問題。比如一個(gè)鏈表是這樣的: 1->2->3->4->5 通過反轉(zhuǎn)后成為5->4->3->2->1。最容易想到的方法遍歷一遍鏈表,利用一個(gè)輔助指針,存儲(chǔ)遍歷過程中當(dāng)前指針指向的下一個(gè)元素,然后將當(dāng)前節(jié)點(diǎn)元素的指針反轉(zhuǎn)后,利用已經(jīng)存儲(chǔ)的指針往后面繼續(xù)遍歷。源代碼如下:

struct linka {
  int data;
  linka* next;
};
void reverse(linka*& head)
{
  if(head ==NULL)
  return;
  linka*pre, *cur, *ne;
  pre=head;
  cur=head->next;
  while(cur)
  {
  ne = cur->next;
  cur->next = pre;
  pre = cur;
  cur = ne;
  }
  head->next = NULL;
  head = pre;
}

還有一種利用遞歸的方法。這種方法的基本思想是在反轉(zhuǎn)當(dāng)前節(jié)點(diǎn)之前先調(diào)用遞歸函數(shù)反轉(zhuǎn)后續(xù)節(jié)點(diǎn)。源代碼如下。不過這個(gè)方法有一個(gè)缺點(diǎn),就是在反轉(zhuǎn)后的最后一個(gè)結(jié)點(diǎn)會(huì)形成一個(gè)環(huán),所以必須將函數(shù)的返回的節(jié)點(diǎn)的next域置為NULL。因?yàn)橐淖僪ead指針,所以我用了引用。算法的源代碼如下:

linka* reverse(linka* p,linka*& head)
{
  if(p == NULL || p->next == NULL)
  {
  head=p;
  return p;
  }
  else
  {
  linka* tmp = reverse(p->next,head);
  tmp->next = p;
  return p;
  }
}

3,判斷兩個(gè)數(shù)組中是否存在相同的數(shù)字給定兩個(gè)排好序的數(shù)組,怎樣高效得判斷這兩個(gè)數(shù)組中存在相同的數(shù)字?
這個(gè)問題首先想到的是一個(gè)O(nlogn)的算法。就是任意挑選一個(gè)數(shù)組,遍歷這個(gè)數(shù)組的所有元素,遍歷過程中,在另一個(gè)數(shù)組中對(duì)第一個(gè)數(shù)組中的每個(gè)元素進(jìn)行binary search。用C++實(shí)現(xiàn)代碼如下:

bool findcommon(int a[],int size1,int b[],int size2)
{
  int i;
  for(i=0;i<size1;i++)
  {
  int start=0,end=size2-1,mid;
  while(start<=end)
  {
   mid=(start+end)/2;
   if(a[i]==b[mid])
    return true;
   else if (a[i]<b[mid])
    end=mid-1;
   else
    start=mid+1;
  }
  }
  return false;
}

后來發(fā)現(xiàn)有一個(gè) O(n)算法。因?yàn)閮蓚€(gè)數(shù)組都是排好序的。所以只要一次遍歷就行了。首先設(shè)兩個(gè)下標(biāo),分別初始化為兩個(gè)數(shù)組的起始地址,依次向前推進(jìn)。推進(jìn)的規(guī)則是比較兩個(gè)數(shù)組中的數(shù)字,小的那個(gè)數(shù)組的下標(biāo)向前推進(jìn)一步,直到任何一個(gè)數(shù)組的下標(biāo)到達(dá)數(shù)組末尾時(shí),如果這時(shí)還沒碰到相同的數(shù)字,說明數(shù)組中沒有相同的數(shù)字。

bool findcommon2(int a[], int size1, int b[], int size2)
{
  int i=0,j=0;
  while(i<size1 && j<size2)
  {
  if(a[i]==b[j])
    return true;
  if(a[i]>b[j])
   j++;
  if(a[i]<b[j])
   i++;
  }
  return false;
}

4,最大子序列問題:
給定一整數(shù)序列A1, A2,... An (可能有負(fù)數(shù)),求A1~An的一個(gè)子序列Ai~Aj,使得Ai到Aj的和最大
例如:
整數(shù)序列-2, 11, -4, 13, -5, 2, -5, -3, 12, -9的最大子序列的和為21。
對(duì)于這個(gè)問題,最簡單也是最容易想到的那就是窮舉所有子序列的方法。利用三重循環(huán),依次求出所有子序列的和然后取最大的那個(gè)。當(dāng)然算法復(fù)雜度會(huì)達(dá)到O(n^3)。顯然這種方法不是最優(yōu)的,下面給出一個(gè)算法復(fù)雜度為O(n)的線性算法實(shí)現(xiàn),算法的來源于Programming Pearls一書。在給出線性算法之前,先來看一個(gè)對(duì)窮舉算法進(jìn)行優(yōu)化的算法,它的算法復(fù)雜度為O(n^2)。其實(shí)這個(gè)算法只是對(duì)對(duì)窮舉算法稍微做了一些修改:其實(shí)子序列的和我們并不需要每次都重新計(jì)算一遍。假設(shè)Sum(i, j)是A[i] ... A[j]的和,那么Sum(i, j+1) = Sum(i, j) + A[j+1]。利用這一個(gè)遞推,我們就可以得到下面這個(gè)算法:

int max_sub(int a[],int size)
{
  int i,j,v,max=a[0];
  for(i=0;i<size;i++)
  {
  v=0;
  for(j=i;j<size;j++)
  {
   v=v+a[j];//Sum(i, j+1) = Sum(i, j) + A[j+1]
   if(v>max)
    max=v;
  }
  }
  return max;
}

那怎樣才能達(dá)到線性復(fù)雜度呢?這里運(yùn)用動(dòng)態(tài)規(guī)劃的思想。先看一下源代碼實(shí)現(xiàn):

int max_sub2(int a[], int size)
{
  int i,max=0,temp_sum=0;
  for(i=0;i<size;i++)
  {
  temp_sum+=a[i];
  if(temp_sum>max)
   max=temp_sum;
  else if(temp_sum<0)
   temp_sum=0;
  }
  return max;
}

6,按單詞反轉(zhuǎn)字符串并不是簡單的字符串反轉(zhuǎn),而是按給定字符串里的單詞將字符串倒轉(zhuǎn)過來,就是說字符串里面的單詞還是保持原來的順序,這里的每個(gè)單詞用空格分開。
如果只是簡單的將所有字符串翻轉(zhuǎn)的話,可以遍歷字符串,將第一個(gè)字符和最后一個(gè)交換,第二個(gè)和倒數(shù)第二個(gè)交換,依次循環(huán)。其實(shí)按照單詞反轉(zhuǎn)的話可以在第一遍遍歷的基礎(chǔ)上,再遍歷一遍字符串,對(duì)每一個(gè)單詞再反轉(zhuǎn)一次。這樣每個(gè)單詞又恢復(fù)了原來的順序。

char* reverse_word(const char* str)
{
  int len = strlen(str);
  char* restr = new char[len+1];
  strcpy(restr,str);
  int i,j;
  for(i=0,j=len-1;i<j;i++,j--)
  {
  char temp=restr[i];
  restr[i]=restr[j];
  restr[j]=temp;
  }
  int k=0;
  while(k<len)
  {
  i=j=k;
  while(restr[j]!=' ' && restr[j]!='' )
   j++;
  k=j+1;
  j--;
  for(;i<j;i++,j--)
  {
   char temp=restr[i];
   restr[i]=restr[j];
   restr[j]=temp;
  }
  }
  return restr;
}

如果考慮空間和時(shí)間的優(yōu)化的話,當(dāng)然可以將上面代碼里兩個(gè)字符串交換部分改為異或?qū)崿F(xiàn)。

例如將
               

 char temp=restr[i];
  restr[i]=restr[j];
  restr[j]=temp;

改為
        

 restr[i]^=restr[j];
   restr[j]^=restr[i];
  restr[i]^=restr[j]; 

7,字符串反轉(zhuǎn)我沒有記錯(cuò)的話是一道MSN的筆試題,網(wǎng)上無意中看到的,拿來做了一下。題目是這樣的,給定一個(gè)字符串,一個(gè)這個(gè)字符串的子串,將第一個(gè)字符串反轉(zhuǎn),但保留子串的順序不變。例如:

輸入:第一個(gè)字符串: "This is mianwww's Chinese site: http://www.mianwww.com.cn/cn"

子串: "mianwww"

輸出: "nc/nc.moc.mianwww.www//:ptth :etis esenihC s'mianwww si sihT"

一般的方法是先掃描一邊第一個(gè)字符串,然后用stack把它反轉(zhuǎn),同時(shí)記錄下子串出現(xiàn)的位置。然后再掃描一遍把記錄下來的子串再用stack反轉(zhuǎn)。我用的方法是用一遍掃描數(shù)組的方法。掃描中如果發(fā)現(xiàn)子串,就將子串倒過來壓入堆棧。

最后再將堆棧里的字符彈出,這樣子串又恢復(fù)了原來的順序。源代碼如下:
#include <iostream>
#include <cassert>
#include <stack>
using namespace std;
//reverse the string 's1' except the substring 'token'.
const char* reverse(const char* s1, const char* token)
{
  assert(s1 && token);
  stack<char> stack1;
  const char* ptoken = token, *head = s1, *rear = s1;
  while (*head != '')
  {
    while(*head!= '' && *ptoken == *head)
    {
    ptoken++;
    head++;
    }
    if(*ptoken == '')//contain the token
    {
    const char* p;
    for(p=head-1;p>=rear;p--)
      stack1.push(*p);
 
    ptoken = token;
    rear = head;
    }
    else
    {
    stack1.push(*rear);
     head=++rear;
    ptoken = token;
    }
  }
  char * return_v = new char[strlen(s1)+1];
  int i=0;
  while(!stack1.empty())
  {
    return_v[i++] = stack1.top();
    stack1.pop();
  }
  return_v[i]='';
  return return_v;
}
int main(int argc, char* argv[])
{cout<<"This is mianwww 's Chinese site: http://www.mianwww.com.cn/cn
";
  cout<<reverse("This is mianwww's Chinese site: http://www. mianwww.com.cn/cn"," mianwww ");
  return 0;
}

 8, 刪除數(shù)組中重復(fù)的數(shù)字問題:一個(gè)動(dòng)態(tài)長度可變的數(shù)字序列,以數(shù)字0為結(jié)束標(biāo)志,要求將重復(fù)的數(shù)字用一個(gè)數(shù)字代替,例如:

將數(shù)組 1,1,1,2,2,2,2,2,7,7,1,5,5,5,0 轉(zhuǎn)變成1,2,7,1,5,0 問題比較簡單,要注意的是這個(gè)數(shù)組是動(dòng)態(tài)的。所以避免麻煩我還是用了STL的vector。

#include <iostream>
#include <vector>
using namespace std;
//remove the duplicated numbers in an intger array, the array was end with 0;
//e.g. 1,1,1,2,2,5,4,4,4,4,1,0 --->1,2,5,4,1,0
void static remove_duplicated(int a[], vector<int>& _st)
{
  _st.push_back(a[0]);
  for(int i=1;_st[_st.size()-1]!=0;i++)
  {
    if(a[i-1]!=a[i])
    _st.push_back(a[i]);
  }
}

當(dāng)然如果可以改變原來的數(shù)組的話,可以不用STL,僅需要指針操作就可以了。下面這個(gè)程序?qū)⑿薷脑瓉頂?shù)組的內(nèi)容。

void static remove_duplicated2(int a[])
{
  if(a[0]==0 || a==NULL)
    return;
  int insert=1,current=1;
  while(a[current]!=0)
  {
    if(a[current]!=a[current-1])
    {
    a[insert]=a[current];
    insert++;
    current++;
    }
    else
    current++;
  }
  a[insert]=0;
}

     
9,如何判斷一棵二叉樹是否是平衡二叉樹問題:判斷一個(gè)二叉排序樹是否是平衡二叉樹解決方案:
根據(jù)平衡二叉樹的定義,如果任意節(jié)點(diǎn)的左右子樹的深度相差不超過1,那這棵樹就是平衡二叉樹。
首先編寫一個(gè)計(jì)算二叉樹深度的函數(shù),利用遞歸實(shí)現(xiàn)。

template<typename T>
static int Depth(BSTreeNode<T>* pbs)
{
  if (pbs==NULL)
    return 0;
  else
  {
    int ld = Depth(pbs->left);
    int rd = Depth(pbs->right);
    return 1 + (ld >rd &#63; ld : rd);
  }
}

下面是利用遞歸判斷左右子樹的深度是否相差1來判斷是否是平衡二叉樹的函數(shù):

template<typename T>
static bool isBalance(BSTreeNode<T>* pbs)
{
  if (pbs==NULL) 
    return true;
  int dis = Depth(pbs->left) - Depth(pbs->right);
  if (dis>1 || dis<-1 )
    return false;
  else
    return isBalance(pbs->left) && isBalance(pbs->right);
4.abstract class Something {
 private abstract String doSomething ();
 }

該段代碼有錯(cuò)嗎?
答案: 錯(cuò)。abstract的methods不能以private修飾。abstract的methods就是讓子類implement(實(shí)現(xiàn))具體細(xì)節(jié)的,怎么可以用private把a(bǔ)bstract method封鎖起來呢&#63; (同理,abstract method前不能加final)。
5.看看下面的代碼段錯(cuò)在哪里?

public class Something {
void doSomething () {
private String s = “”;
int l = s.length();
}
}

答案: 錯(cuò)。局部變量前不能放置任何訪問修飾符 (private,public,和protected)。final可以用來修飾局部變量
(final如同abstract和strictfp,都是非訪問修飾符,strictfp只能修飾class和method而非variable)。
6. 下面該段代碼是否有錯(cuò),若是有錯(cuò)錯(cuò)在哪里?

abstract class Name {
private String name;
public abstract boolean isStupidName(String name) {}
}

答案: 錯(cuò)。abstract method必須以分號(hào)結(jié)尾,且不帶花括號(hào)。

關(guān)于常見的Java中數(shù)據(jù)結(jié)構(gòu)面試題問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI