在單鏈表中刪除倒數(shù)第k個節(jié)點(diǎn)

題目

??**分別實(shí)現(xiàn)兩個函數(shù),一個可以刪除單鏈表中倒數(shù)第 K 個節(jié)點(diǎn),另一個可以刪除雙鏈表中倒數(shù)第 K 個節(jié)點(diǎn)

要求

??如果鏈表長度為 N,時間復(fù)雜度達(dá)到O(N),額外空間復(fù)雜度達(dá)到O(1)。

思路

??本題較為簡單,實(shí)現(xiàn)方式也是多種多樣的,小編提供一種方法供讀者參考。
??先來看看單鏈表如何調(diào)整。如果鏈表為空或者 K 小于1。這種情況下,參數(shù)是無效的直接返回即可,除此之外,讓鏈表從頭開始走到尾,每移動一步,就讓K的值減1。
??鏈表: 1 → 2 → 3,K = 4,鏈表根本不存在倒數(shù)第4個節(jié)點(diǎn)
??走到的節(jié)點(diǎn): 1 → 2 → 3
??K 變化為: 3 2 1
??鏈表: 1 → 2 → 3,K = 3,鏈表倒數(shù)第3個節(jié)點(diǎn)是1節(jié)點(diǎn)
??走到的節(jié)點(diǎn): 1 → 2 → 3
??K 變化為: 2 1 0
??鏈表: 1 → 2 → 3,K = 2,鏈表倒數(shù)第2個節(jié)點(diǎn)是2節(jié)點(diǎn)
??鏈表:走到的節(jié)點(diǎn): 1 → 2 → 3
??K 變化為:1 → 0 → 1
??由以上三種情況可知,讓鏈表從頭開始走到尾,沒移動一步,就讓 K 值減1,當(dāng)鏈表走到結(jié)尾時,如果值大于0。說明不用調(diào)整鏈表,因?yàn)殒湵砀緵]有倒數(shù)第 K 個節(jié)點(diǎn),此時將原鏈表直接返回即可;如果 K 值等于0,說明鏈表倒數(shù)第 K 個節(jié)點(diǎn)就是頭節(jié)點(diǎn),此時直接返回head.next,也就是原鏈表的第二個節(jié)點(diǎn),讓第二個節(jié)點(diǎn)作為鏈表的頭節(jié)點(diǎn)返回即可,相當(dāng)于刪除頭節(jié)點(diǎn);接下來,說明一下如果 K 值小于0,該如何處理。
??先明確一點(diǎn),如果要刪除鏈表的頭節(jié)點(diǎn)之后的某個節(jié)點(diǎn),實(shí)際上需要找到要刪除節(jié)點(diǎn)的前個節(jié)點(diǎn),比如: 1 → 2 → 3,如果想除節(jié)點(diǎn)2,則需要找到節(jié)點(diǎn)1,然后把節(jié)點(diǎn)1連到節(jié)點(diǎn)3上(1 → 3),以此來達(dá)到刪除節(jié)點(diǎn)2的目的。
??如果 K 值小于0,如何找到要刪除節(jié)點(diǎn)的前一個節(jié)點(diǎn)呢?方法如下:
??1.重新從頭節(jié)點(diǎn)開始走,每移動一步,就讓K的值加1。
??2.當(dāng)K等于0時,移動停止,移動到的節(jié)點(diǎn)就是要刪除節(jié)點(diǎn)的前一個節(jié)點(diǎn)。
??這樣做是非常好理解的,因?yàn)槿绻湵黹L度為N,要刪除倒數(shù)第K個節(jié)點(diǎn),很明顯,倒數(shù)第 K 個節(jié)點(diǎn)的前一個節(jié)點(diǎn)就是第 N - K 個節(jié)點(diǎn)。在第一次遍歷后,K 的值變?yōu)?K - N。第二次遍歷時 K 的值不斷加1,加到 0 就停止遍歷,第二次遍歷當(dāng)然會停到第 N - K個節(jié)點(diǎn)的位置。

代碼演示

package com.itz.zcy.listQuestion;

/**
 * 分別實(shí)現(xiàn)兩個函數(shù),一個可以刪除單鏈表中倒數(shù)第 K 個節(jié)點(diǎn),另一個可以刪除雙鏈表中倒數(shù)第 K 個節(jié)點(diǎn)
 * 如果鏈表長度為 N,時間復(fù)雜度達(dá)到O(N),額外空間復(fù)雜度達(dá)到O(1)。
 */
public class DeleteListKNode {

    /**
     * 定義節(jié)點(diǎn)
     */
    public static class Node {
        public int value;
        public Node next;
        //該變量用來做雙鏈表的指向前區(qū)節(jié)點(diǎn),在單鏈表的時候請讀者忽略該節(jié)點(diǎn)
        public Node last;

        public Node(int data) {
            this.value = data;
        }
    }

    /**
     * 刪除單鏈表的倒數(shù)第k個節(jié)點(diǎn)
     * @param head
     * @param lastKth
     * @return
     */
    public static Node removeLastKthNode(Node head, int lastKth) {
//        異常判定
        if (head == null || lastKth < 1) {
            return head;
        }
//        輔助節(jié)點(diǎn)
        Node cur = head;
//        遍歷一遍節(jié)點(diǎn)判斷節(jié)點(diǎn)在鏈表的哪兒
        while (cur != null) {
            lastKth--;
            cur = cur.next;
        }
//        如果是刪除頭節(jié)點(diǎn)的情況
        if (lastKth == 0){
            head = head.next;
        }
//        找到要刪除的節(jié)點(diǎn)
        if (lastKth < 0) {
            cur = head;
            while (++lastKth != 0) {
                cur = cur.next;
            }
//            刪除節(jié)點(diǎn)
            cur.next = cur.next.next;
        }
        return head;
    }

    /**
     * 刪除雙鏈表的倒數(shù)第k個節(jié)點(diǎn)
     * @param head
     * @param lastKth
     * @return
     */
    public static Node removeLastKthDoubleNode(Node head,int lastKth){
        if (head==null||lastKth<1){
            return head;
        }

        Node cur = head;
        while (cur !=null){
            lastKth--;
            cur = cur.next;
        }
        if (lastKth == 0){
            head = head.next;
            head.last = null;
        }

        if (lastKth<0){
            cur = head;
            while (++lastKth!=0){
                cur = cur.next;
            }
//            刪除節(jié)點(diǎn) 刪除雙鏈表的某個節(jié)點(diǎn)
            Node newNext = cur.next.next;
            cur.next = newNext;
            if (newNext != null){
                newNext.last = cur;
            }
        }
        return head;
    }

    public static void main(String[] args) {
        Node node = new Node(2);
        node.next = new Node(4);
        node.next.next = new Node(6);
        node.next.next.next = new Node(8);
        node.next.next.next.next = new Node(3);
        node.next.next.next.next.next = new Node(5);
        node.next.next.next.next.next.next = new Node(7);
        Node head = removeLastKthNode(node, 5);
        while (true){
            if (head!=null){
                if (head.next == null){
                    System.out.print(head.value);
                }else {
                    System.out.print(head.value+" → ");
                }
            }else {
                break;
            }
            head = head.next;
        }

        System.out.println();
        Node node2 = new Node(2);
        node2.next = new Node(4);
        node2.next.last= node2;
        node2.next.next = new Node(6);
        node2.next.next.last = node2.next;
        node2.next.next.next = new Node(8);
        node2.next.next.next.last = node2.next.next;
        node2.next.next.next.next = new Node(3);
        node2.next.next.next.next.last = node2.next.next.next;
        node2.next.next.next.next.next = new Node(5);
        node2.next.next.next.next.next.last = node2.next.next.next.next;
        node2.next.next.next.next.next.next = new Node(7);
        node2.next.next.next.next.next.next.last = node2.next.next.next.next.next;
        Node head2 = removeLastKthDoubleNode(node2, 5);
        while (true){
            if (head2!=null){
                if (head2.next == null){
                    System.out.print(head2.value);
                }else {
                    System.out.print(head2.value+" ? ");
                }
            }else {
                break;
            }
            head2 = head2.next;
        }
    }

//    2 → 4 → 8 → 3 → 5 → 7
//    2 ? 4 ? 8 ? 3 ? 5 ? 7
}

總結(jié)

該題目比較簡單,方法多種多樣;時間復(fù)雜度是O(n),空間復(fù)雜度O(1)。

文獻(xiàn):左程云著 《程序員代碼面試指南IT名企算法與數(shù)據(jù)結(jié)構(gòu)題目最優(yōu)解》(第二版)
版權(quán)聲明:此文版權(quán)歸作者所有!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 【題目】分別實(shí)現(xiàn)兩個函數(shù),一個可以刪除單鏈表中倒數(shù)第k個節(jié)點(diǎn),另一個可以刪除雙鏈表中倒數(shù)第k個節(jié)點(diǎn)?!窘馕觥肯葋矸?..
    Airycode閱讀 584評論 0 0
  • 搞懂單鏈表常見面試題 Hello 繼上次的 搞懂基本排序算法,這個一星期,我總結(jié)了,我所學(xué)習(xí)和思考的單鏈表基礎(chǔ)知識...
    醒著的碼者閱讀 4,733評論 1 45
  • 題目 輸入一個鏈表,輸出該鏈表中倒數(shù)第k個節(jié)點(diǎn)。 為了符合大多數(shù)人的習(xí)慣,本題從1開始計(jì)數(shù),即鏈表的尾節(jié)點(diǎn)是倒數(shù)第...
    Longshihua閱讀 302評論 0 2
  • URL字符串中的字符 參考:RFC2396 RFC1738 URL中使用的字符必須來自ASCII的一個固定的子集,...
    HRocky閱讀 494評論 0 0
  • 我們總是在晚上變的格外敏感。 普通的話語也要思索上好幾遍,看電視連續(xù)劇情感也容易共鳴,本來沒有那么傷心的事情在晚上...
    e5ab6748334f閱讀 213評論 0 1

友情鏈接更多精彩內(nèi)容