昨天在最後給你們留了拓展題,不知道你們有沒有思考完成,其實南塵說有巨坑是嚇你們的啦,實際上也沒什麼。咱們來繼續看看昨天這個拓展題。java
面試題:給定單鏈表的頭結點,刪除單鏈表的倒數第 k 個結點。node
前面的文章見連接:面試 7:面試常見的鏈表算法捷徑(一)面試
這個題和前面的文章中增長了一個操做,除了找出來這個結點,咱們還要刪除它。刪除一個結點,想必你們一定也知道:要想操做(添加、刪除)單鏈表的某個結點,那咱們還得知道這個節點的前一個節點。因此咱們要刪除倒數第 k 個結點,就必需要找到倒數第 k+1 個結點。而後把倒數第 k+1 個元素的 next 變量 p.next 指向 p.next.next。算法
咱們找到倒數第 k 個結點的時候,先讓 fast 走了 k-1 步,而後再讓 slow 變量和 fast 同步走,它們之間就會一直保持 k-1 的距離,因此當 fast 到鏈表尾結點的時候,slow 剛剛指向的是倒數第 k 個結點。this
本題因爲咱們要知道倒數第 k+1 個結點,因此得讓 fast 先走 k 步,待 fast 指向鏈表尾結點的時候,slow 正好指向倒數第 k+1 個結點。spa
咱們簡單思考一下臨界值:code
因此咱們天然能獲得這樣的代碼。ci
public class Test07 { public static class LinkNode { int data; LinkNode next; public LinkNode(int data) { this.data = data; } } private static LinkNode delTheSpecifiedReverse(LinkNode head, int k) { LinkNode slow = head; LinkNode fast = head; if (fast == null) { throw new RuntimeException("your linkNode is null"); } // 先讓 fast 先走 k 步 for (int i = 0; i < k; i++) { if (fast == null) { // 說明輸入的 k 已經超過了鏈表長度,直接報錯 throw new RuntimeException("the value k is too large."); } fast = fast.next; } // fast == null ,說明已經到了尾結點後面的空區域,說明要刪除的就是頭結點。 if (fast == null) { return head.next; } while (fast.next != null) { slow = slow.next; fast = fast.next; } slow.next = slow.next.next; return head; } public static void main(String[] args) { LinkNode head = new LinkNode(1); head.next = new LinkNode(2); head.next.next = new LinkNode(3); head.next.next.next = new LinkNode(4); head.next.next.next.next = new LinkNode(5); LinkNode node = delTheSpecifiedReverse(head, 3); while (node != null) { System.out.print(node.data + "->"); node = node.next; } } }
好了,咱們解決了昨天文章中留下的拓展題,今天咱們來看看咱們鏈表都還有些怎樣的考法。同步
面試題:定義一個單鏈表,輸入一個鏈表的頭結點,反轉該鏈表並輸出反轉後鏈表的頭結點。爲了方便,咱們鏈表的 data 採用整型。string
這是一道反轉鏈表的經典題,咱們來屢一下思路:一個結點包含下一結點的引用,反轉的意思就是要把原來指向下一結點的引用指向上一個結點。咱們能夠分爲下面的步驟:
用代碼實現就是:
public class Test08 { private static class LinkNode { int data; LinkNode next; LinkNode(int data) { this.data = data; } } private static LinkNode reverseLink(LinkNode head) { // 上一個結點 LinkNode nodePre = null; LinkNode next = null; LinkNode node = head; while (node != null) { // 先用 next 保存下一個要反轉的結點,否則會致使鏈表斷裂。 next = node.next; // 再把如今結點的 next 引用指向上一個結點 node.next = nodePre; // 把當前結點賦值給 nodePre 變量,以便於下一次賦值 nodePre = node; // 向後遍歷 node = next; } return nodePre; } public static void main(String[] args) { LinkNode head = new LinkNode(1); head.next = new LinkNode(2); head.next.next = new LinkNode(3); head.next.next.next = new LinkNode(4); head.next.next.next.next = new LinkNode(5); LinkNode node = reverseLink(head); while (node != null) { System.out.print(node.data + "->"); node = node.next; } } }
鏈表能夠考的可真多,相信不是小夥伴都和我同樣,雲裏霧裏了,那咱們今天就講到這裏,後面還要繼續考算法,你,打起精神,別睡着了。