每日三题-合并两个有序链表、相交链表、删除链表的第N个节点

简介: 每日三题删除链表的倒数第N个结点合并两个有序链表相交链表

删除链表的倒数第N个结点


69a0821282bb4125b7cf8237b68e0887.png

解法一

使用双指针

新建一个头节点,避免出现删除头节点出现异常的情况比如[1],1 就会出现问题因为slow.next = slow.next.next 中slow.next会报空指针异常

而新建一个节点后 [newHead,1],1,slow为newhead,那就不会出现空指针异常,并且这个时候的slow就是要删除节点的前一个节点

不需要维护一个pre节点

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if(head == null || n == 0) return head;
        ListNode newHead = new ListNode(0,head); // 有可能删除的是头节点
        ListNode slow = newHead; // slow 保存的是需要删除节点的前一个节点
        ListNode quick = head;
        while(quick != null && n != 0){ // 找到比他快n的节点
            quick = quick.next;
            n--;
        }
        while(quick != null){  // 同时往后移动
            quick = quick.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return newHead.next;
    }
}


合并两个有序链表


44eee921294a4a91a2a98544b416ffbd.png

解法一

双指针

list1指向第一个节点,list2指向第二个节点,同时比较大小,谁小就往后移动

如果list1为空了,则把t指向list2,反之同理

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if(list1 == null) return list2;
        if(list2 == null) return list1;
        ListNode res = new ListNode();
        ListNode t = res;
        while(list1 != null && list2 !=null){
            if(list1.val < list2.val){
                t.next = list1;
                list1 = list1.next;
            }else{
                t.next = list2;
                list2 = list2.next;
            }
            t = t.next;
        }
        if(list1 != null)t.next = list1; // 为空直接指向另一个指针
        if(list2 != null)t.next = list2;
        return res.next;
    }
}

相交链表


a4e547c1850c47dbb6517a808e8d00a3.png


解法一

使用双指针

ta指向headA,tb指向headB

ta,tb同时往后移,如果为空了,则将当前节点设置为另一个链表的头节点

原理

有相交

A [a1,a2,c1,c2,c3]

B [b1,b2,b3,c1,c2,c3]

则当ta走完A链表时候走的长度为a+c,当b走完B链表时候长度为b+c

则ta指向B,tb指向A

ta为c1时候走的长度为a+c+b

tb为c1时候走的长度为b+c+a

没有相交

A[a1,a2]

B[b1,b2,b3]

则A==B的时候只有A == B ==null的时候

所有当ta到达B的末尾null时候走的路程为a+b

tb走到A的末尾null时候走的路程为b+a

所有也可以退出循环

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB ==null) return null;
        ListNode ta = headA;
        ListNode tb = headB;
        while(ta != tb){
            ta = ta != null ? ta.next:headB;
            tb = tb != null ? tb.next:headA;
        }
        return ta;
    }
}

解法二

使用哈希集合

把A中节点保存到一个集合,然后循环B中节点,如果集合中有就说明有相交直接返回,如果没有最后返回null

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB ==null) return null;
        HashSet<ListNode> s = new HashSet<>();
        while(headA!=null){
            s.add(headA);
            headA = headA.next;
        }
        while(headB!=null){
            if(s.contains(headB)) return headB;
            headB = headB.next;
        }
        return null;
    }
}



相关文章
|
1月前
|
Python
【Leetcode刷题Python】21. 合并两个有序链表
介绍了几种不同的方法来合并多个已排序的链表,包括暴力求解、使用小顶堆以及分而治之策略。
29 2
|
23天前
|
算法
LeetCode第24题两两交换链表中的节点
这篇文章介绍了LeetCode第24题"两两交换链表中的节点"的解题方法,通过使用虚拟节点和前驱节点技巧,实现了链表中相邻节点的交换。
LeetCode第24题两两交换链表中的节点
|
23天前
|
算法
LeetCode第21题合并两个有序链表
该文章介绍了 LeetCode 第 21 题合并两个有序链表的解法,通过创建新链表,依次比较两个链表的头节点值,将较小的值插入新链表,直至其中一个链表遍历完,再将另一个链表剩余部分接到新链表后面,实现合并。
LeetCode第21题合并两个有序链表
|
25天前
|
算法
【算法】合并两个有序链表(easy)——递归算法
【算法】合并两个有序链表(easy)——递归算法
【算法】合并两个有序链表(easy)——递归算法
|
2月前
【数据结构OJ题】相交链表
力扣题目——相交链表
23 1
【数据结构OJ题】相交链表
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
38 5
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 18. 删除链表的节点
Leetcode题目"剑指 Offer 18. 删除链表的节点"的Python解决方案,通过使用双指针法找到并删除链表中值为特定数值的节点,然后返回更新后的链表头节点。
30 4
|
2月前
【数据结构OJ题】合并两个有序链表
力扣题目——合并两个有序链表
33 8
【数据结构OJ题】合并两个有序链表
|
1月前
|
算法 Python
【Leetcode刷题Python】106.相交链表
采用双指针法来找出两个链表的相交起始节点,并详细解释了算法的时间和空间复杂度。
15 1
|
2月前
|
安全 云计算
云计算自旋锁问题之在线程安全地删除链表节点时,需要频繁加锁会影响性能如何解决
云计算自旋锁问题之在线程安全地删除链表节点时,需要频繁加锁会影响性能如何解决
35 2