題目:
輸入乙個鍊錶,輸出該鍊錶中倒數第k個結點,為了符合大多數人的習慣,本題從1開始計數,即鍊錶的尾結點是倒數第乙個結點,例如:乙個鍊錶有6個結點,從頭結點開始他們的值依次是1,2,3,4,5,6.這個鍊錶的倒數第三個結點是值為4的結點。
分析:這是乙個很經典的老的題,如果第一次看到這個題的話,可能想的是遍歷一邊鍊錶得到長度為n,然後再從頭來一邊,找到第n-k個鍊錶,就是倒數第k個結點。那麼時間複雜度就是o(n),但是如果告訴你還有一種方法使得它只遍歷一邊就能得到結果,你會怎麼想?
可能就會做乙個k大小的佇列,當佇列的頭指向了最後乙個結點的時候,那佇列的尾指向的就是此鍊錶的倒數第k個結點。但是如果題目要求你只有常數的空間複雜度怎麼辦。其實能想到佇列,這個題就基本相當於想到了最佳答案,因為在佇列裡,只用到了頭和尾,中間的儲存空間是沒有用的,那麼我們就把中間的都去掉,只留下頭和尾,就相當於用兩個指標,第乙個指標先向前移動k個結點,然後第二個指標跟著第乙個指標依次向後移動,直到第乙個指標指向鍊錶的尾結點,那麼第二個指標指向的就是倒數第k個結點。
能想到這一點,這個題就算做完了?
沒有吧!
如果k比鍊錶的總長度還大怎麼辦?
所以**的魯棒性就要很好的體現了!
下面看**:
int findlastknode(listnode * headlist,int k)
while(pnext != null)
return p->m_nvalue;
}
劍指offer這本書上還對此題目進行了擴充套件,有幾個擴充套件的題目還是比較不錯的
1.求鍊錶的中間結點。如果鍊錶的結點總數為奇數,返回中間結點,如果結點總數是偶數,返回中間兩個結點的任意乙個。
答:我們也可以定義兩個指標,都同時指向頭結點,乙個指標一次走一步,另乙個指標一次走兩步。當走的快的那個指標指向了尾結點,那麼走的慢的指標就指向的中間結點。
2.判斷乙個單項鍊表是不是形成了環形結構。
這個問題和前面的問題一樣,乙個走兩步,乙個走兩步,如果走的快的指標追上了走的慢的,那麼就是有環的。如果走的快的指向了尾結點,那麼說明這個鍊錶沒有環。
總結:當我們嘗試用乙個指標遍歷鍊錶不能解決問題的時候,可以嘗試用兩個指標來遍歷鍊錶,可以讓其中乙個指標速度快點,或者讓它先走幾步。
劍指offer 15 鍊錶中倒數第k個結點
package listtest.findknode 輸入乙個鍊錶,輸出該鍊錶中倒數第k個結點。思路 定義兩個指標,第乙個指標從鍊錶的頭指標開始遍歷向前走k 1,第二個指標保持不動,從第k步開始,第二個指標也開始從鍊錶的頭指標開始遍歷。兩個指標距離保持在k 1,當第乙個指標到達鍊錶的尾結點時,第二個...
劍指offer 15 鍊錶中倒數第k個結點
class listnode 題目 輸入乙個鍊錶輸出鍊錶的倒數第k個結點 解法 設定兩個標記,先讓第乙個走k步,接著讓他們同步移動,知道第乙個到末尾,第二個則為倒數第二個結點 public class main public static listnode reverselist listnode ...
劍指offer 15 鍊錶中倒數第n個節點
輸入乙個鍊錶,輸出該鍊錶中倒數第k個節點。為了符合大多數人的習慣,本題從1開始,即鍊錶的尾節點是倒數第乙個節點。例如乙個鍊錶有6個節點,從第乙個節點開始它們的值是1 2 3 4 5 6。這個鍊錶倒數第3個節點是值為4的節點。指定兩個指標pbefore和pafter,均指向第乙個節點,起先前面的指標p...