編程之美_單鏈表面試題_結合3.4_3.6 .

轉載於:http://blog.csdn.net/insistgogo/article/details/7584240

一、單鏈表結點的刪除

0、刪除單鏈表p指向的那個元素,(時間和空間複雜度儘量小)

二、單鏈表的存取

1、找出單鏈表的倒數第K個元素,(僅允許遍歷一遍鏈表)

2、找出單鏈表的中間元素,(僅允許遍歷一遍鏈表)

三、單鏈表與環的問題

3、判斷單鏈表是否有環(6形狀)?

4、如何找到環的入口?

5、如何知道環的長度?

6、帶環鏈表的長度是多少?

四、單鏈表與相交、環的問題

7、如何知道兩個單鏈表(無環)是否相交

8、如果兩個單鏈表(無環)相交,如何知道它們相交的第一個節點是什麼

9、如何知道兩個單鏈表(有環)是否相交

10、如果兩個單鏈表(有環)相交,如何知道它們相交的第一個節點是什麼


~~~~~~~~~~~華麗的分割線~~~~~~~~~~~~~~

一、單鏈表結點的刪除

0、刪除單鏈表p指向的那個元素,(時間和空間複雜度儘量小)

思路:把q指向結點的值 賦給 p指向的結點,再把q指向結點刪除

二、單鏈表的存取

1、找出單鏈表的倒數第K個元素,(僅允許遍歷一遍鏈表)

思路:使用指針追趕的方法。定義兩個指針fast和slowfast先走K步,然後從這時開始,fastslow同時繼續走,即fast和slow相差K個元素當fast到頭時,slow指向倒數第K個。注意要考慮鏈表長度應該大於K

2、找出單鏈表的中間元素,(僅允許遍歷一遍鏈表)

思路:使用指針追趕的方法。使用兩個指針fastslow,只是fast每次走一步,slow每次走兩步。當fast到頭時,slow指向鏈表的中間元素

三、單鏈表與環的問題


3、判斷單鏈表是否有環(6形狀)?

思路:使用指針追趕的方法,設定兩個指針fast、slow,從頭指針開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到NULL退出。

  1. while(直到步長2的跑到結尾)  
  2. {  
  3.     檢查兩個指針是否相等,直到找到爲止。  
  4. }  

4、如何找到環的入口?

圖說明:如上圖,h是鏈表起始點,s是環入口,p是兩個指針碰撞點。r  = x + y 

可以證明, a = y + mr  (頭指針 到 環入口的距離 = 碰撞點到 環入口的距離   +  循環多次環 )

附錄處有證明

思路:令兩個指針分別從第一個結點、碰撞點開始走,每一次走一步,直到兩指針相遇,此時相遇的那個點就是入口

5、如何知道環的長度?

思路:記錄下問題4的碰撞點p(或者找在環中任意一結點都可以),讓slow從碰撞點開始,繞着環走一圈,再次到碰撞點的位置時,所走過的結點數就是環的長度s。(一個指針從起始點出發走一圈,再次到起始點,就是走了環一圈)

6、帶環鏈表的長度是多少?

思路:帶環鏈表長度 = a + x + y = 鏈表起始點h 到 環起始點s的距離 + 環的長度 。在第4題中可以找到a的值,在第5題可以找到 環的長度(x+y)的值

四、單鏈表與相交、環的問題

7、如何知道兩個單鏈表(無環)是否相交


思路:

1、判斷兩鏈表最後一個節點是否相同,如果相交,則尾節點肯定是同一節點。

時間複雜度O((length(A)+ length(B))、空間複雜度 = O(1)(存儲最後結點的地址)


2、人爲構環,如上圖。將鏈表A的尾節點指向鏈表B,如果B鏈表有環,則兩個鏈表相交,此時從鏈表B的頭指針往下遍歷,如果能夠回到B,則說明相交

時間複雜度O((length(A)+ length(B)),沒有額外的空間消耗

8、如果兩個單鏈表(無環)相交,如何知道它們相交的第一個節點是什麼

思路:

1、先取得兩個鏈表A和B的長度len(A)和len(B)

2、沿着A和B鏈表中較長的鏈表遍歷,使用指針追趕的方法。

設定兩個指針fast、slow。fast先出發前進(lengthMax-lengthMin)步(即是二者的長度之差)使fast和slow指針到相交點的距離相等,之後兩個鏈表同時前進,每次一步,相遇的第一點即爲兩個鏈表相交的第一個點。

9、如何知道兩個單鏈表(可能有環)是否相交

思路:根據兩個鏈表是否有環來分別處理

1、如果兩個鏈表都沒有環。可用 問題7 來判斷

2、一個有環,一個沒環。肯定不相交

3、兩個都有環。(注,兩個有環鏈表相交是指這個環屬於兩個鏈表共有

具體方法:如果兩個都有環,則求出A的環入口,判斷其是否在B鏈表上,如果在,則相交。

或者,在A鏈表上,使用指針追趕的方法,找到兩個指針碰撞點,之後判斷碰撞點是否在B鏈表上。如果在,則相交 。

10、如果兩個單鏈表(有環)相交,如何知道它們相交的第一個節點是什麼

注,兩個有環鏈表相交是指這個環屬於兩個鏈表共有

情況1:相交的點,在環外


思路:使用指針追趕的方法。

1、求兩個鏈表A和B的長度Length(A)和Length(B)

2、如果Length(A)> Length(B),則鏈表A指針先走 Length(A)-  Length(B),鏈表B指針再開始走,則兩個指針相遇的位置就是相交的第一個節點。

      如果 Length(B)> Length(A,則鏈表B指針先走 Length(B)- Length(A),鏈表A指針再開始走,則兩個指針相遇的位置就是相交的第一個節點。

情況2(圖2)、相交的點,在環內,還不能處理


分析:當交點在環中時,此時的交點可以是A鏈表中的環入口點,也可以是B鏈表中環入口點。

爲什麼這麼說?這是因爲如果把B看出一個完整的鏈表,而A指向了B鏈表,則此時交點是A的環入口點。反之交點是鏈表B的環入口點。

思路:根據上述分析,可以直接求出A的環入口點或者B的環入口點就可以了。

綜合這兩種情況,給出兩個方法求出結點

方法一、先檢測交點是否在第一種情況中。如果是,則直接輸出該結點。如果不是,則直接輸出任意一個環交點。

方法二、使用哈希,只需要把鏈表A或者B所有的元素全部放入哈希表中,之後把B鏈表或者A鏈表中的每一個元素去哈希探測,即可找到交點。

附錄1、

4、如何找到環的入口?
圖說明:如圖,h是鏈表起始點,s是環入口,p是兩個指針碰撞點。r表示環的長度,r = x+y

可以證明, a = y + mr  (頭指針 到 環入口的距離 = 碰撞點p 到 環入口的距離   +  循環多次環 )


證明:

當fast若與slow相遇時,slow肯定沒有走遍歷完鏈表,而fast已經在環內循環了n圈(1<=n)。

假設slow走了s步,則fast走了2s步(fast步數還等於s 加上在環上多轉的n圈)。

設環長爲r,則:

2s = s + nr,即s= nr

設整個鏈表長L,入口環與相遇點距離爲x,起點到環入口點的距離爲a。

s = nr

a + x = nr

a + x = (n – 1)r +r = (n-1)r + r

a = (n-1)r + r - x

a = (n-1)r + y

由此可知,從鏈表頭到環入口點等於(n-1)循環內環+ 相遇點到環入口點,於是我們從鏈表頭、與相遇點分別設一個指針,每次各走一步,兩個指針必定相遇,且相遇第一點爲環入口點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章