劍指offer 鏈表專題

鏈表的特性:
如下代碼:

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode result = new ListNode (3),pre = result;
        pre.next = l1;
        return result;
    }
}

劍指offer 06 從尾到頭打印鏈表
時(shí)間復(fù)雜度O(n)
空間復(fù)雜度O(n)

/**
* Definition for singly-linked list.
* public class ListNode {
*     int val;
*     ListNode next;
*     ListNode(int x) { val = x; }
* }
*/
class Solution {
   public int[] reversePrint(ListNode head) {
       // 檢查鏈表長(zhǎng)度
       //注意:node -> 2 -> 3 
       // node.next = 2   node.next.next = 3 所以不能直接用head.next進(jìn)while循環(huán)
       ListNode curNode = head;
       int len = 0;
       while (curNode != null){
           len++;
           curNode = curNode.next;
       }

       //建立一個(gè)相同長(zhǎng)度的List
       int[] l1 = new int[len];

       //將鏈表倒序裝入List中
       curNode = head;
       while(len>0){
           l1[len-1] = curNode.val;
           curNode = curNode.next;
           len--;
       }
       return l1;
   }
}

劍指offer 22 鏈表中倒數(shù)第k個(gè)節(jié)點(diǎn)
快慢指針亩码,先讓快指針走k步瓮孙,然后兩個(gè)指針同步走鲁僚,當(dāng)快指針走到頭時(shí)祈搜,慢指針就是鏈表倒數(shù)第k個(gè)節(jié)點(diǎn)比搭。

class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        ListNode curNode = head;
        while(curNode != null){
            curNode = curNode.next;
            if (k == 0){
                head = head.next;
            }
            else{
                k--;
            }
        }
        return head;
    }
}

劍指offer 24 反轉(zhuǎn)鏈表

1 -> 2 -> 3 -> null  => 3->2->1->null
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = head;
        ListNode cur = null;
        while(pre != null){
            head = head.next;        //將head移至下一位
            pre.next = cur;          // 修改 next 引用指向
            cur = pre;               // cur 暫存 pre
            pre = head;  
        }
        return cur;
    }
}

注解:為何while循環(huán)不可以寫成:

pre.next = cur;          // 修改 next 引用指向
cur = pre;               // cur 暫存 pre
head = head.next;        //將head移至下一位
pre = head;  

因?yàn)橹?code>pre和head同時(shí)指向了
1 -> 2 -> 3 -> null => 3->2->1->null
pre.next = cur;已經(jīng)改變了鏈表結(jié)構(gòu)擦囊,所以后面head = head.next已經(jīng)不是原本指向的head

劍指offer 25 合并兩個(gè)排序的鏈表

輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode result = new ListNode(0);     //建造一個(gè)偽頭節(jié)點(diǎn)
        ListNode temp = result;             //temp用來增加節(jié)點(diǎn)蝗羊,result和temp同時(shí)指向同一個(gè)鏈表

        while(l1 != null && l2 != null){
            if(l1.val >= l2.val){
                temp.next = l2;
                temp = temp.next;
                l2 = l2.next;
            }
            else{
                temp.next = l1;
                temp = temp.next;
                l1 = l1.next;
            }
        }
        if(l1 == null){
            temp.next = l2;
        }
        else if(l2 == null){
            temp.next = l1;
        }
        //拋去偽頭節(jié)點(diǎn)
        return result.next;
    }
}

劍指offer 35 復(fù)雜鏈表的復(fù)制

HashMap:

class Solution {
    public Node copyRandomList(Node head) {
        Map<Node,Node> map = new HashMap<>();
        Node cur = head;
        while(cur != null){
            // cur是原來的,在這里充當(dāng)key; 后者是新建的,充當(dāng)value
            //map{7(old):7(new constructed),13:13,... }
            map.put(cur,new Node(cur.val));
            cur = cur.next;
        }

        cur = head;
        while(cur != null){
            //map.get(cur)是new Node 構(gòu)造出來的,體現(xiàn)出deep copy
            // .next 是做指向。map.get(cur.next)也是新Node
            map.get(cur).next = map.get(cur.next);  
            map.get(cur).random = map.get(cur.random);
            cur = cur.next;
        }
        //取出,因?yàn)閏ur已經(jīng)移位到最后了骤菠,故用head亦可
        return map.get(head);
    }
}

合并拆分:

class Solution {
    public Node copyRandomList(Node head) {
        if(head == null){return null;} //先考慮head =null 情況
        Node cur = head;
        while(cur != null){
            // temp = 7
            Node temp = new Node(cur.val);
            //temp= 7->13->11->...
            temp.next = cur.next;
            // cur= 7->7->13->11->...
            cur.next = temp;
            //cur= 13->11->...
            cur = temp.next;
        }
        //調(diào)整cur至最前node
        cur = head;
        //匹配random
        while(cur != null){
            //不能同時(shí)處理random和next原因是:當(dāng)設(shè)定 7->7->3->3->...新7next為新3時(shí),鏈表斷裂無法進(jìn)行
            // cur.next.next = cur.next.next.next;
            if(cur.random != null){
                cur.next.random = cur.random.next;
            }
            cur = cur.next.next;
        }
        // 拆分兩鏈表
        cur = head.next;
        Node pre = head, res = head.next;
        while(cur.next != null) {
            pre.next = pre.next.next;
            cur.next = cur.next.next;
            pre = pre.next;
            cur = cur.next;
        }
        pre.next = null; // 必須要把head也還原好疤孕,不要忘了單獨(dú)處理原鏈表尾節(jié)點(diǎn)
        return res;      // 返回新鏈表頭節(jié)點(diǎn)
    }
}

劍指offer 52 兩個(gè)鏈表的第一個(gè)公共節(jié)點(diǎn)
雙指針解法:雙方在最后加上對(duì)方不同的部分商乎,最終會(huì)相遇
時(shí)間:O(M+N) 兩個(gè)鏈表長(zhǎng)度 ? 空間: O(1)

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode hA = headA;
        ListNode hB = headB;
        //雙指針: uncommonA+common+B = uncommonB+common+A
        while(hA != hB){
            if(hA == null){hA = headB;}
            else hA = hA.next;
            
            if(hB == null){hB = headA;}
            else hB = hB.next;
        }
        return hA;
    }
}

劍指offer 18 刪除鏈表的節(jié)點(diǎn)*

輸入: head = [4,5,1,9], val = 5
輸出: [4,1,9]
class Solution {
    public ListNode deleteNode(ListNode head, int val) {
        // 引入偽頭節(jié)點(diǎn)
        ListNode dummyhead = new ListNode(0);
        dummyhead.next = head;
        // 指針cur開始進(jìn)行判定
        ListNode cur = dummyhead;
        while(cur.next != null){
            if(cur.next.val != val){
                cur = cur.next;
            }
            else {
                cur.next = cur.next.next;
            }
        }
        // 返回
        return dummyhead.next;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市祭阀,隨后出現(xiàn)的幾起案子鹉戚,更是在濱河造成了極大的恐慌,老刑警劉巖柬讨,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崩瓤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡踩官,警方通過查閱死者的電腦和手機(jī)却桶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔗牡,“玉大人颖系,你說我怎么就攤上這事”缭剑” “怎么了嘁扼?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)黔攒。 經(jīng)常有香客問我趁啸,道長(zhǎng),這世上最難降的妖魔是什么督惰? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任不傅,我火速辦了婚禮,結(jié)果婚禮上赏胚,老公的妹妹穿的比我還像新娘访娶。我一直安慰自己,他們只是感情好觉阅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布崖疤。 她就那樣靜靜地躺著,像睡著了一般典勇。 火紅的嫁衣襯著肌膚如雪劫哼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天割笙,我揣著相機(jī)與錄音沦偎,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛豪嚎,可吹牛的內(nèi)容都是我干的搔驼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼侈询,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼舌涨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起扔字,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤囊嘉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后革为,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扭粱,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年震檩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了琢蛤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抛虏,死狀恐怖博其,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情迂猴,我是刑警寧澤慕淡,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站沸毁,受9級(jí)特大地震影響峰髓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜息尺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一携兵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧掷倔,春花似錦眉孩、人聲如沸个绍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)巴柿。三九已至凛虽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間广恢,已是汗流浹背凯旋。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人至非。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓钠署,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親荒椭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谐鼎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容