力扣记录:链表——19 删除链表的倒数第N个节点,面试题02.07 链表相交,142 环形链表II

本次题目

  • 19 删除链表的倒数第N个节点
  • 面试题02.07 链表相交
  • 142 环形链表II

19 删除链表的倒数第N个节点

  • 建议使用虚拟头结点,方便处理删除头结点的情况。
  • 双指针:快指针比慢指针快N+1个节点,当快指针指向链表末尾时慢指针指向倒数第N+1个节点,方便删除第N个节点(删除慢指针指向的下一个节点)。
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //定义虚拟头结点
        ListNode virtualHead = new ListNode(0);
        virtualHead.next = head;
        //定义快慢指针
        ListNode fast = virtualHead;
        ListNode slow = virtualHead;
        //使快指针先前进n+1
        for(int i = 0; i <= n; i++){
            fast = fast.next;
        }
        //快慢指针同时前进,直到快指针指向null
        while(fast != null){
            fast = fast.next;
            slow = slow.next;
        }
        //删除slow指向节点的下一个节点
        slow.next = slow.next.next;
        return virtualHead.next;

    }
}

面试题02.07 链表相交

  • 求两个链表交点节点的指针,交点是指针相等而不是数值相等,从交点开始直到末尾的节点数值都相同,因此可以将两个链表的末尾对齐,指针指向较短链表的头结点开始向链表末尾前进遍历。
  • 注意:判断两个链表谁长谁短,可以通过始终设置链表A为较长链表从而减少代码重复。
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //分别定义两个遍历指针
        ListNode curA = headA;
        ListNode curB = headB;
        //分别计算两个链表长度
        int lenA = 0;
        int lenB = 0;
        while(curA != null){
            lenA++;
            curA = curA.next;
        }
        while(curB != null){
            lenB++;
            curB = curB.next;
        }
        //重新初始化两个遍历指针
        curA = headA;
        curB = headB;
        //判断两个链表长度
        if(lenA > lenB){ //链表A比B长
            //两个遍历指针都指向短链表的头结点位置
            for(int i = 0; i < lenA-lenB; i++){
                curA = curA.next;
            }
            //开始对比
            while(curA != null){
                if(curA == curB){
                    return curA;
                }
                curA = curA.next;
                curB = curB.next;
            }
        }else{ //链表B比A长
            //两个遍历指针都指向短链表的头结点位置
            for(int i = 0; i < lenB-lenA; i++){
                curB = curB.next;
            }
            //开始对比
            while(curA != null){
                if(curA == curB){
                    return curA;
                }
                curA = curA.next;
                curB = curB.next;
            }
        }
        return null;
    }
}

142 环形链表II

  • 判断链表是否有环:双指针(快慢指针),快慢指针先后从头结点出发,快指针每次移动两个节点,慢指针每次移动一个节点,若快慢指针相遇,则链表有环(快追慢)。注意:链表长度不能小于2。
  • 判断环的入口:数学分析,设从快慢指针相遇节点出发到环入口节点的长度z,从头结点出发到环入口节点的长度x,从环入口节点到快慢指针相遇节点的长度为y,由慢指针走过的点数 * 2 = 快指针走过的点数,得到(x+y)2=x+y+n(y+z),即x=(n-1)(y+z)+z,其中,n为大于等于1的整数,(y+z)为环的长度。因此,两个指针分别从头结点和快慢指针相遇位置出发,每次移动一个节点,相遇的位置就是环入口节点
public class Solution {
    public ListNode detectCycle(ListNode head) {
        //定义快慢指针
        ListNode fast = head;
        ListNode slow = head;
        //判断是否有环,快慢指针分别前进两个单位和一个单位
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            //快慢指针相遇,存在环
            if(fast == slow){
                //定义两个指针;分别从头结点和相遇节点出发
                ListNode index1 = fast;
                ListNode index2 = head;
                while(index1 != index2){
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值