算法Day4|24-两两交换链表中的节点;19-删除链表的倒数第N个节点;160-链表相交;142-环形链表II

55 阅读2分钟

前言

链表刷题结束。

1、题目1:24-两两交换链表中的节点

题目:leetcode.cn/problems/sw…

类型:中等

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

代码:

public static ListNode swapPairs(ListNode head) {
    ListNode dummp = new ListNode(0);
    dummp.next = head;
    ListNode curr = dummp;
    
    while (curr.next!=null && curr.next.next!=null){
        ListNode first = curr.next;
        ListNode next = curr.next.next;
        ListNode temp = next.next;
        curr.next = next;
        next.next = first;
        first.next = temp;

        curr=curr.next.next;
    }
    return dummp.next;
}

2、题目2:19-删除链表的倒数第N个节点

题目:leetcode.cn/problems/re…

难度:简单

思路:

双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode dummy = new ListNode();
    dummy.next =head;
    ListNode fast=dummy,curr=dummy;
    for (int i = 0; i < n; i++) {
        curr = curr.next;
    }
    while (curr.next!=null){
        curr = curr.next;
        fast = fast.next;
    }
    fast.next = fast.next.next;
    return dummy.next;
}

3、题目3:160-链表相交

题目:leetcode.cn/problems/in…

类型:简单

链表如果相交,那相交的位置就是 C1,难点在于使用两个指针,如何让它们同时达到 C1 节点,

假设:设置 a 的长度是 x+z ;b 的长度是 y+z。

  • x+z = y+z
  • x+z+y = y+z+x

即,双指针,A 指针当遍历完 A 链表,再遍历 B 链表;B 指针遍历 B 链表后再遍历 A 链表后,

此时存在首个相交的节点,要么存在,要么为null,返回这个值即可。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
                ListNode p1 =headA,p2=headB;
        while (p1!=p2){
           // p1 走一步,如果走到 A 链表末尾,转到 B 链表
            if(p1 == null){
                p1=headB;
            }else{
                p1=p1.next;
            }
            if(p2 == null){
                p2=headA;
            }else{
                p2 =p2.next;
            }
        }
        return p1;
    }
}

4、题目4:142-环形链表II

题目:leetcode.cn/problems/li…

类型:中等

又是个需要分析和计算的题目。

这个环形问题,就是让两指针分别以1慢1快的速度开始。

Slow 指针每次走1步,fast 指针每次走2步,找到相遇点后,让某个指针回到head节点行走k-m即到环的节点位置。

ListNode fast,slow;
fast = slow = head;
while (fast!=null && fast.next!=null){
    fast = fast.next.next;
    slow=slow.next;
    if(fast == slow){
        break;
    }
}
// fast 代表遇到空指针
if(fast == null || fast.next == null){
    return null;
}
slow = head;
while (slow!=fast){
    fast = fast.next;
    slow=slow.next;
}
return slow;

5、总结

链表的经典题目页都刷过了,关于是否要添加虚拟头结点 :虚拟头结点的主要目的是为了避免对头结点的特殊处理;这个处理就指的是修改操作。所以可以这样:涉及到对链表修改(如插入,删除,移动)的,都加个dummy,只是遍历取点就可以不用加。