劍指Offer——鏈表中的倒數第K個節點

那麼多學技術的都可以成功,憑什麼我不行

鏈表中的倒數第K個節點

本文基於《劍指Offer》 使用Java代碼實現

更多《劍指Offer》Java實現合集

 

題目

  輸入一個鏈表,輸出該鏈表中倒數第k個結點。爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾結點是倒數第1個結點。例如一個鏈表有6個結點,從頭結點開始它們的值依次是1、2、3、4、5、6。這個鏈表的倒數第3個結點是值爲4的結點。

 

思路

  第一直覺是先從頭開始遍歷,計算鏈表個數n,然後重新遍歷,第n-k+1個結點即爲所需要的結點。但是需要遍歷2次。後面採用了棧進行實現該方法,空間複雜度比較大。書中的方法則是:設置兩個指針,第一個指針先遍歷k-1步;從第k步開始,第二個指針指向頭結點,兩個結點同時往後遍歷,當第一個指針到達最後一個結點時,第二個指針指向的正好是倒數第k個結點。

 

代碼實現

利用棧實現

/**
 * @ClassName: KthNodeFromEnd
 * @description: 面試題22: 鏈表中的倒數第K個節點
 * @author: XZQ
 * @create: 2020/4/27 9:27
 **/  
//方法1:利用棧
    public ListNode FindKthToTail1(ListNode head, int k) {
        if (head == null || k <= 0)//如果頭節點爲空指針或者k<=0
            return null;
        Stack<ListNode> stack = new Stack<>();
        ListNode curNode = head;
        int listLength = 0;
        while (curNode != null) {
            listLength++;
            stack.push(curNode);
            curNode = curNode.next;
        }
        if (k > listLength) {
            return null;
        }
        for (int i = 0; i < k; i++) {
            curNode = stack.pop();
        }
        return curNode;
    }

利用兩個指針

//方法2:利用兩個指針,
    // 一個指針先向前走k-1步,第二個開始遍歷,當第一個指針走到鏈表尾部時,第二個指針恰好在倒數第k個節點
    public ListNode FindKthToTail2(ListNode head, int k) {
        if (head == null || k <= 0)//如果頭節點爲空指針或者k<=0
            return null;
        ListNode node1 = head;
        ListNode node2 = null;
        /*node1先向前走k-1步*/
        for (int i = 0; i < k - 1; i++) {
            if (node1.next != null) {
                node1 = node1.next;
            } else {
                return null;
            }
        }
        node2 = head;
        while (node1.next != null) {
            node1 = node1.next;
            node2 = node2.next;
        }
        return node2;
    }

測試

 public static void main(String[] args) {
        ListNode p6 = new ListNode(6, null);
        ListNode p5 = new ListNode(5, p6);
        ListNode p4 = new ListNode(4, p5);
        ListNode p3 = new ListNode(3, p4);
        ListNode p2 = new ListNode(2, p3);
        ListNode p1 = new ListNode(1, p2);
        ListNode node = new KthNodeFromEnd().FindKthToTail2(p1, 4);
        if ((node != null)) {
            System.out.println(node.val);
        } else {
            System.out.println("test failed!");
        }

    }

輸出

4

收穫

  1.注意代碼的魯棒性,開始思考前都需要注意特殊輸入測試;

  2.一個指針遍歷鏈表無法解決問題時,可以考慮使用兩個指針來遍歷鏈表:兩個指針先後遍歷(即該題目)、或者兩個指針遍歷速度不同(如:求鏈表中的中間結點,可以令一個指針一次走一步,另一個指針一次走兩步來實現)

 更多《劍指Offer》Java實現合集

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