day04 142.环形链表II&& 面试题 02.07. 链表相交&&19.删除链表的倒数第N个节点&&24. 两两交换链表中的节点

  1. 环形链表 II(142. Linked List Cycle II)
    问题描述:给定一个链表,返回链表开始入环的第一个节点。如果链表无环,则返回null。
    解决方案:
    //142.环形链表II
    public ListNode detectCycle(ListNode head) {
    ///耗时较长
    Set set = new HashSet<>();
    ListNode cur = head;
    while (cur != null) {
    if (set.contains(cur)) {
    return cur;
    }
    set.add(cur);
    cur = cur.next;
    }
    return null;
    /
    ListNode slow = head;
    ListNode fast = head;
    boolean isCycle = false;
    while (fast != null && fast.next != null) {
    slow = slow.next;
    fast = fast.next.next;
    if (slow == fast) {
    isCycle=true;
    break;
    }
    }
    //从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点,
    // 那么当这两个指针相遇的时候就是 环形入口的节点。
    if (isCycle) {
    slow = head;
    while (fast != slow) {
    fast = fast.next;
    slow = slow.next;
    }
    return slow;
    }
    return null;
    }
    解释:
    使用快慢指针法检测环的存在。
    如果检测到环,将一个指针重置为链表的头节点,然后两个指针同时向前移动,每次移动一步,当两个指针再次相遇时,该点即为环的入口。

  2. 面试题 02.07. 链表相交
    问题描述:给定两个单链表,判断它们是否相交,如果相交,返回相交的起始节点。
    解决方案:
    //面试题 02.07. 链表相交
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) {
    return null;
    }
    ListNode a=headA,b=headB;
    int aLen=0,bLen=0;
    while (a != null) {
    aLen++;
    a=a.next;
    }
    while (b != null) {
    bLen++;
    b=b.next;
    }
    a=headA;
    b=headB;
    int diff=Math.abs(aLen-bLen);
    if(aLen>bLen){
    //int diff=aLen-bLen;
    for(int i=0;i<diff;i++){
    a=a.next;
    }
    while(a!=null){
    if(ab){
    return a;
    }
    a=a.next;
    b=b.next;
    }
    }else {
    //int diff=bLen-aLen;
    for(int i=0;i<diff;i++){
    b=b.next;
    }
    while(b!=null){
    if(b
    a){
    return b;
    }
    b=b.next;
    a=a.next;
    }
    }
    return null;
    }
    /(版本二) 合并链表实现同步移动
    public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    // p1 指向 A 链表头结点,p2 指向 B 链表头结点
    ListNode p1 = headA, p2 = headB;
    while (p1 != p2) {
    // p1 走一步,如果走到 A 链表末尾,转到 B 链表
    if (p1 == null) p1 = headB;
    else p1 = p1.next;
    // p2 走一步,如果走到 B 链表末尾,转到 A 链表
    if (p2 == null) p2 = headA;
    else p2 = p2.next;
    }
    return p1;
    }
    }
    /
    解释:
    计算两个链表的长度。
    将较长的链表的指针移动到与较短链表相同长度的位置。
    同时移动两个指针,如果相遇则返回该节点,否则返回null。

  3. 删除链表的倒数第N个节点(19. Remove Nth Node From End of List)
    问题描述:给定一个链表,删除链表的倒数第n个节点,并返回新的链表头节点。
    解决方案:
    // 19.删除链表的倒数第N个节点
    public ListNode removeNthFromEnd(ListNode head, int n) {
    int size = 0;
    ListNode dummy = new ListNode(Integer.MIN_VALUE,head);
    ListNode cur = dummy.next;
    while (cur!= null) {
    size++;
    cur = cur.next;
    }
    if (size == n) {
    return head.next;
    }
    cur=dummy;
    for (int i = 0; i < size - n; i++) {
    if (cur != null) {
    cur = cur.next;
    }
    }
    if (cur!=null&&cur.next != null) {
    cur.next=cur.next.next;
    }
    return dummy.next;
    }
    解释:
    使用一个哨兵节点dummy,其next指针指向链表的头节点。
    计算链表的长度size。
    如果要删除的节点是头节点,直接返回head.next。
    否则,找到倒数第n+1个节点,将其next指针指向倒数第n-1个节点,从而删除倒数第n个节点。

  4. 两两交换链表中的节点(24. Swap Nodes in Pairs)
    问题描述:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
    解决方案:
    //24. 两两交换链表中的节点
    public ListNode swapPairs(ListNode head) {
    if (head == null || head.next == null) {
    return head;
    }
    ListNode cur1=head;
    ListNode cur2=head.next;
    ListNode res=cur2;
    ListNode temp;
    while (true){
    temp=cur2.next;
    cur1.next=temp;
    cur2.next=cur1;
    if(tempnull){
    break;
    } else if (temp.next
    null) {
    break;
    }else {
    cur1.next=temp.next;
    }
    cur1=temp;
    cur2=temp.next;
    }
    return res;
    }
    解释:
    如果链表为空或只有一个节点,直接返回原链表。
    使用两个指针cur1和cur2分别指向当前节点和下一个节点。
    交换两个节点,并更新指针。
    重复上述步骤,直到链表结束。

posted @ 2025-01-18 01:26  123木头人-10086  阅读(90)  评论(0)    收藏  举报