每日三题-合并两个有序链表、相交链表、删除链表的第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月前
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
48 0
Leetcode第21题(合并两个有序链表)
|
1月前
|
存储 算法
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
88 0
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-160、相交链表)
❤️算法笔记❤️-(每日一刷-160、相交链表)
17 1
|
1月前
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
17 0
LeetCode第二十四题(两两交换链表中的节点)
|
1月前
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
40 0
Leetcode第十九题(删除链表的倒数第N个节点)
|
1月前
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
46 0
|
1月前
【数据结构】环形、相交、回文、分割、合并、反转链表
【数据结构】环形、相交、回文、分割、合并、反转链表
28 0
|
3月前
|
算法
LeetCode第24题两两交换链表中的节点
这篇文章介绍了LeetCode第24题"两两交换链表中的节点"的解题方法,通过使用虚拟节点和前驱节点技巧,实现了链表中相邻节点的交换。
LeetCode第24题两两交换链表中的节点
05_删除链表的倒数第N个节点
05_删除链表的倒数第N个节点