剑指offer 链表专题

链表的特性:
如下代码:

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

剑指offer 06 从尾到头打印链表
时间复杂度O(n)
空间复杂度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) {
       // 检查链表长度
       //注意:node -> 2 -> 3 
       // node.next = 2   node.next.next = 3 所以不能直接用head.next进while循环
       ListNode curNode = head;
       int len = 0;
       while (curNode != null){
           len++;
           curNode = curNode.next;
       }

       //建立一个相同长度的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 链表中倒数第k个节点
快慢指针,先让快指针走k步,然后两个指针同步走,当快指针走到头时,慢指针就是链表倒数第k个节点。

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 反转链表

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循环不可以写成:

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

因为之前prehead同时指向了
1 -> 2 -> 3 -> null => 3->2->1->null
pre.next = cur;已经改变了链表结构,所以后面head = head.next已经不是原本指向的head

剑指offer 25 合并两个排序的链表

输入: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);     //建造一个伪头节点
        ListNode temp = result;             //temp用来增加节点,result和temp同时指向同一个链表

        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;
        }
        //抛去伪头节点
        return result.next;
    }
}

剑指offer 35 复杂链表的复制

HashMap:

class Solution {
    public Node copyRandomList(Node head) {
        Map<Node,Node> map = new HashMap<>();
        Node cur = head;
        while(cur != null){
            // cur是原来的,在这里充当key; 后者是新建的,充当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 构造出来的,体现出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;
        }
        //取出,因为cur已经移位到最后了,故用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;
        }
        //调整cur至最前node
        cur = head;
        //匹配random
        while(cur != null){
            //不能同时处理random和next原因是:当设定 7->7->3->3->...新7next为新3时,链表断裂无法进行
            // 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也还原好,不要忘了单独处理原链表尾节点
        return res;      // 返回新链表头节点
    }
}

剑指offer 52 两个链表的第一个公共节点
双指针解法:双方在最后加上对方不同的部分,最终会相遇
时间:O(M+N) 两个链表长度   空间: 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 删除链表的节点*

输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
class Solution {
    public ListNode deleteNode(ListNode head, int val) {
        // 引入伪头节点
        ListNode dummyhead = new ListNode(0);
        dummyhead.next = head;
        // 指针cur开始进行判定
        ListNode cur = dummyhead;
        while(cur.next != null){
            if(cur.next.val != val){
                cur = cur.next;
            }
            else {
                cur.next = cur.next.next;
            }
        }
        // 返回
        return dummyhead.next;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容