【剑指offer】day1 - 4道常规链表题 | Java

39 阅读2分钟

今天要解决四道关于链表的常规题,点击链接直达力扣,冲冲冲!🤪

L1 删除链表的节点

基础题,双指针一前一后。注意删除头节点 + 空节点。

此题对比原题有改动,但难度系数其实是相同的,都是考查删除节点的基本功,只不过原题直接告诉了要删除的节点,不用找了,所以是O(1)的。

时间复杂度:O(n)
空间复杂度:O(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteNode(ListNode head, int val) {
        if(head==null){
            return null;
        }
        if(head.val==val){
            return head.next;
        }
        ListNode cur=head.next;
        ListNode pre=head;
        while(cur!=null){
            if(cur.val==val){
                pre.next=cur.next;
                return head;
            }
            pre=pre.next;
            cur=cur.next;
        }
        return head;
    }
}

L2 链表中倒数第K个节点

基础题,快慢指针。注意起点是1还是0。

时间复杂度:O(n)
空间复杂度:O(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode trainingPlan(ListNode head, int cnt) {
        ListNode fast=head;
        ListNode slow=head;
        while(cnt>0){
            fast=fast.next;
            cnt--;
        }
        while(fast!=null){
            slow=slow.next;
            fast=fast.next;
        }
        return slow;
    }
}

L3 合并两个排序的链表

常规题,拉拉链。注意最后没排完的链表可以直接连上,不用一个个节点接上。

时间复杂度:O(n+m),n 和 m 表示两个链表长度
空间复杂度:O(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode trainningPlan(ListNode l1, ListNode l2) {
        ListNode dummy=new ListNode(-1);
        ListNode p1=l1,p2=l2;
        ListNode cur=dummy;
        while(p1!=null&&p2!=null){
            if(p1.val<=p2.val){
                cur.next=p1;
                p1=p1.next;
            }else{
                cur.next=p2;
                p2=p2.next;
            }
            cur=cur.next;
        }
        if(p1!=null){
            cur.next=p1;
        }
        if(p2!=null){
            cur.next=p2;
        }
        return dummy.next;

    }
}

L4 两个链表的第一个公共点

由于本题是不存在环的,所以相对容易,可以直接遍历计算节点数量之差,也可以采用双指针,不过建议理解双指针的方法,代码优雅。

时间复杂度:O(n+m),n 和 m 表示两个链表长度
空间复杂度:O(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
class Solution {
    ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA==null||headB==null)return null;
        ListNode p1=headA,p2=headB;
        while(p1!=p2){
            p1= p1==null?headB:p1.next;
            p2= p2==null?headA:p2.next;
        }
        return p1;
        
    }
}

总结

链表的技巧,老生常谈了哈。就那么两点:双指针(包括快慢指针、左右指针...)、虚拟头节点。

如果本文对你有帮助的话,不妨点个小赞👍帮助更多的小伙伴!!!