JAVA二刷-Day4 24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点, 面试题 02.07. 链表相交, 142.环形链表II

本文介绍了四道LeetCode上的JAVA链表题目,包括两两交换链表中的节点、删除链表的倒数第N个节点、判断链表相交以及寻找环形链表II的解题思路和代码实现,涉及链表操作的基本算法和技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JAVA二刷-Day4 | 24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点, 面试题 02.07. 链表相交, 142.环形链表II

两两交换链表中的节点

LeetCode题目链接:https://leetcode.cn/problems/remove-linked-list-elements/

解题思路

  先看题目,因为是要两两进行交换,所以与直接翻转有所不同。需要考虑更多的情况,比如头结点的更换问题。为了避免特殊处理,添加虚拟头结点。之后,因为两两反转后,指向第三个节点的部分也出现了改变,因此第三个节点也需要用额外的临时变量进行存储。

  因此,首先初始化一个虚拟头结点来作为当前的头结点,再补充一个临时变量,进行迭代。

  代码如下:

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummyHead = new ListNode(-1, head);
        ListNode temp,curr,pre;

        ListNode dhead = dummyHead;
        
        while (dhead != null && dhead.next != null && dhead.next.next != null) {
            pre = dhead.next;
            curr = dhead.next.next;
            temp = dhead.next.next.next;
            dhead.next = curr;
            curr.next = pre;
            pre.next = temp;
            dhead = pre;
        }
        
        return dummyHead.next;


    }
}

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

LeetCode题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list

解题思路

  删去倒数第n个元素,那么首先要知道整个链表的长度,在已知链表长度的基础上,可以得出倒数第n个值是正数的第几个节点。

  此后,设置一个节点用于到达该位置,另一个节点集合该位置之前的点。便完成了删除节点的操作。

  具体代码如下:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyHead = new ListNode(-1, head);
        ListNode slow = dummyHead, fast = dummyHead;

        while (n != 0 && fast!=null) {
            fast = fast.next;
            n--;
        }

        while (fast.next != null) {
            slow = slow.next;
            fast = fast.next;
        }

        slow.next = slow.next.next;
        
        return dummyHead.next;

    }
}

链表相交

LeetCode题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

解题思路

  需要判定两个链表的相交部分,主要需要保持两个链表的节点更新始终保持到尾部的距离相同。这样才能同步去判定节点位置是否相交。但是因为两个链表长度不定,因此需要先计算出链表的长度。再使长度不等的链表中较长的链表去除头部元素,使其到尾部节点的距离相同,再进行迭代,就可以轻松判定出是否相交了。

具体代码如下:

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int lenA = 0, lenB = 0, offset = 0;
        ListNode temp = headA;
        while (temp != null) {
            temp = temp.next;
            lenA++;
        }

       temp = headB;
        while (temp != null) {
            temp = temp.next;
            lenB++;
        }
        offset = Math.abs(lenA - lenB);
        if (lenA > lenB) {
            while (offset != 0 && headA !=null) {
                headA = headA.next;
                offset--;
            }
        }else if (lenB > lenA) {
            while (offset != 0 && headB != null) {
                headB = headB.next;
                offset--;
            }
        }

        while (headA != null && headB != null) {
            if (headA == headB) {
                return headA;
            }
            headA = headA.next;
            headB = headB.next;
        }

        return null;
    }
}

环形链表II

LeetCode题目链接:https://leetcode.cn/problems/linked-list-cycle-ii

解题思路

  先看题目,首先需要判断链表是否有环,因此可以进行判断,一旦指针在迭代时出现->next=NULL则说明不存在环形,跳出循环并返回NULL。

  之后进行环形判断,当链表存在环形,易得快慢指针一定存在交点。假设从链表起点到环形起点的距离为 x x x,环形起点到交点的距离为 y y y,交点到环形起点的距离为 z z z 。可以得到以下公式:

当快慢指针相遇时有,其中 ( x + y ) (x+y) (x+y)为慢指针的移动距离,由于快指针是慢指针的二倍,所以乘以2后等式成立:
2 ( x + y ) = x + y + n ∗ ( y + z ) 2(x + y) = x +y +n*(y+z) 2(x+y)=x+y+n(y+z)
化简可以得到:
x + y = n ∗ ( y + z ) x+y = n*(y+z) x+y=n(y+z)
即可以求得链表起点到环形起点的距离公式,如果得到 x x x即可得出环形的起点位置:
x = ( n − 1 ) ∗ ( y + z ) + z x = (n-1)*(y+z) + z x=(n1)(y+z)+z
同时,可以观察到 y + z y+z y+z为一个环形,因此可以看作:从交点位置出发,与从链表头出发,一定会在环形的起点处相遇。

  注意,因为fast和slow开始是相同的,所以不能while时候直接判定fast == slow。会导致无法进入循环。

  代码如下:

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow  = head, fast = head;

        while (fast != null && fast.next !=null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                fast = head;
                while (slow != fast) {
                    slow = slow.next;
                    fast = fast.next;
                }
                return slow;
            }
        }
        return null;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值