每日算法:2024/07/26

题目一:19. 删除链表的倒数第 N 个结点

题目思路

核心思想:典型的双指针题目

定义两个指针,其中一个快指针先走 n 或者 n+1 步,具体的区别后面说明,然后再将快指针和慢指针同时向前移动,直到快指针走到链表的尾部null处为止,此时,如果最开始快指针走了 n 步,那么此时的慢指针指向的节点就是待删除的节点,如果最开始快指针走了 n+1 步,此时慢指针指向的就是待删除节点的上一个节点。

  • 如果快指针走 n 步,此时需要额外定义一个变量保存慢指针指向节点的前一个节点,因为快指针指向链表尾部null时,慢指针指向的就是待删除节点,而如果想要删除待删除节点,需要通过它的上一个元素进行删除,因此有必要在移动慢指针前先保存一下他的前一个节点。

  • 如果快指针走 n+1 步,此时当快指针指向链表尾部null时,慢指针指向的就是待删除元素的上一个节点,此时直接删除慢指针指向的下一个节点即可,具体方法slow.next = slow.next.next

题解代码

/*
    fast先走n步以后,再和慢指针同时走,
    直到fast指针走到链表最后的null处,此时slow对应的就是待删除的节点
 */
public ListNode removeNthFromEnd(ListNode head, int n) {
    // 哨兵节点
    ListNode s = new ListNode(-1, head);
    ListNode fast = s.next; // 快指针
    ListNode slow = s.next; // 慢指针
    ListNode prev = s;
    // fast先走n步,需要额外定义一个prev指针指向待删除节点的上一个节点
    for (int i = 0; i < n; i++) {
        fast = fast.next;
    }
    while (fast != null) {
        fast = fast.next;
        // 每次移动slow节点,先记录下来当前slow再移动,此时的prev就是slow节点的前一个节点
        prev = slow;
        slow = slow.next;
    }
    // 将slow节点删除
    prev.next = slow.next;
    return s.next;
}
---------------------------------------------------------------------------------------------
/*
    fast先走n+1步以后,再和慢指针同时走,
    直到fast指针走到链表最后的null处,此时slow对应的就是待删除节点的上一个节点
*/
public ListNode removeNthFromEnd2(ListNode head, int n) {
    // 哨兵节点
    ListNode s = new ListNode(-1, head);
    ListNode fast = s;
    ListNode slow = s;
    // fast先走n+1步,不需要额外定义一个prev指针指向待删除节点的上一个节点
    for (int i = 0; i < n + 1; i++) {
        fast = fast.next;
    }
    while (fast != null) {
        fast = fast.next;
        slow = slow.next;
    }
    // 将slow指针指向的下一个节点从链表中删除
    slow.next = slow.next.next;
    return s.next;
}

题目二:面试题 02.07. 链表相交

题目思路

  1. 双指针:定义两个指针,其中一个指针(currA)遍历链表A,另一个指针(currB)遍历链表B,当currA遍历完链表A后,将其指向链表B的头节点继续遍历链表B,同理,currB指针在遍历完链表B后指向链表A的头结点继续遍历链表A

      因此我们只需要在死循环中判断两指针如果相同,则返回其中一个指针指向的节点即可。(无论有没有相交,最终两指针都会相同,不需要考虑死循环问题)

    1. 如果链表A和链表B有相交节点,则指针currA和currB会同时到达相交节点

    2. 如果没有相交节点,则两个指针会同时指向null

题解代码

/*
    A链表走完走B链表,B链表走完走A链表,如果有相交在循环一次以后一定会同时到达相交节点
    如果没有相交会走完A和B链表同时到达NULL
 */
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    ListNode currA = headA;
    ListNode currB = headB;
    while (true) {
        // 无论是否有无相交,都会在该循环最后走到A,B两个指针相等
        // 有交点,同时指向相交节点 返回相交节点
        // 无交点,同时指向null节点 返回null
        if (currA == currB) {
            return currA;
        }

        if (currA == null) {
            currA = headB; // 走完A链表走B链表
        } else {
            currA = currA.next;
        }

        if (currB == null) {
            currB = headA; // 走完B链表走A链表
        } else {
            currB = currB.next;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值