《 java 随想录》| LeetCode链表高频考题

发布于:2025-07-30 ⋅ 阅读:(12) ⋅ 点赞:(0)

前言:这是专门针对java语言讲解的算法解析(题目顺序大致参考《代码随想录》)

思维导图

操作链表

删除节点

链表-删除节点

删除链表中 D 节点时,只需将其前驱节点 C 的 next 指针指向 D 的下一个节点 E

添加节点

链表-添加节点

先让 新节点 F 的 next 指针 指向 C 原来的后继节点 D(保存原有连接,避免链表断裂);

再让 C 节点的 next 指针 指向 新节点 F,完成插入。

链表基础代码

public class ListNode {
    // 结点的值
    int val;

    // 下一个结点
    ListNode next;

    // 节点的构造函数(无参)
    public ListNode() {
    }

    // 节点的构造函数(有一个参数)
    public ListNode(int val) {
        this.val = val;
    }

    // 节点的构造函数(有两个参数)
    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

LeetCode203. 移除链表元素


一、核心逻辑:通过虚拟头节点统一移除逻辑

链表中每个节点包含值和指向下一节点的引用,要移除值为目标值的节点,可引入虚拟头节点(不存储实际数据),使其作为原头节点的前驱。这样无论是头节点还是中间节点,都能通过 “前驱节点指针调整” 的方式统一处理,避免头节点特殊处理的繁琐。

二、关键细节:虚拟头节点的使用与指针遍历

移除链表元素的难点在于头节点与其他节点处理逻辑不一致,而虚拟头节点可消除这种差异。通过维护一个遍历指针,始终指向当前待检查节点的前驱,就能统一执行 “跳过目标节点” 的操作。

解法:虚拟头节点 + 前驱指针遍历

区间(逻辑范围)含义:以虚拟头节点为起点,遍历指针 prev 始终指向当前处理节点的前驱,待检查范围是 prev.next 及之后的节点。
循环条件:while (prev.next != null)
因为只要 prev 的下一个节点存在,就需要检查其是否为目标值,循环继续。
指针调整:

  • 若 prev.next.val == val:说明下一个节点是目标节点,需移除,因此将 prev.next 指向 prev.next.next(跳过目标节点)。
  • 若 prev.next.val != val:说明下一个节点无需移除,prev 后移一位(prev = prev.next),继续检查后续节点。
    返回结果:循环结束后,所有目标节点已被移除,返回虚拟头节点的下一个节点(即新的头节点)

代码示例:

public ListNode removeElements(ListNode head, int val) {
    while(head!=null && head.val==val) {
        head = head.next;
    }
    ListNode curr = head;
    while(curr!=null && curr.next !=null) {
        if(curr.next.val == val){
            curr.next = curr.next.next;
        } else {
            curr = curr.next;
        }
    }
    return head;
}

LeetCode206. 反转链表


如果再定义一个新的链表,实现链表元素的反转,其实这是对内存空间的浪费

其实只需改变链表的next指针的指向直接将链表反转 ,而非重新定义一个新的链表,如图:

206_反转链表

我们拿有示例中的链表来举例,如动画所示

  • 初始化指针:cur 指向头节点,pre 初始化为 null,tmp 用于临时保存节点。
  • 当 cur 不为 null 时,执行以下操作:
  • 保存下一个节点:用 tmp 存储 cur 的 next 节点(避免后续指向改变后丢失)。
  • 反转当前节点指向:将 cur 的 next 指向 pre。
  • 移动指针:pre 移至 cur 位置,cur 移至 tmp 位置(即之前保存的下一个节点)。
  • 结果处理:循环结束后,pre 指向反转后链表的新头节点,返回 pre。

代码实现:

// 双指针
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode cur = head;
        ListNode temp = null;
        while (cur != null) {
            temp = cur.next;// 保存下一个节点
            cur.next = prev;
            prev = cur;
            cur = temp;
        }
        return prev;
    }

LeetCode24. 两两交换链表中的节点


这道题目正常模拟就可以了。

建议使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。

接下来就是交换相邻两个元素了,此时一定要画图,不画图,操作多个指针很容易乱,而且要操作的先后顺序

初始时,cur指向虚拟头结点,然后进行如下三步:

操作之后,链表如下:

看这个可能就更直观一些了:

代码实现:

public ListNode swapPairs(ListNode head) {
    ListNode dummy = new ListNode(0, head);
    ListNode cur = dummy;
    while (cur.next != null && cur.next.next != null) {
        ListNode node1 = cur.next;// 第 1 个节点
        ListNode node2 = cur.next.next;// 第 2 个节点
        cur.next = node2; // 步骤 1
        node1.next = node2.next;// 步骤 3
        node2.next = node1;// 步骤 2
        cur = cur.next.next;
    }
    return dummy.next;
}

LeetCode19. 删除倒数第n个节点


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

分为如下几步:

  • 定义fast指针和slow指针,初始值为虚拟头结点,如图:

  • fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图: 

  • fast和slow同时移动,直到fast指向末尾,如题: 

  • 删除slow指向的下一个节点,如图: 

代码实现:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //新建一个虚拟头节点指向head
        ListNode dummyNode = new ListNode(0);
        dummyNode.next = head;
        //快慢指针指向虚拟头节点
        ListNode fastIndex = dummyNode;
        ListNode slowIndex = dummyNode;

        // 只要快慢指针相差 n 个结点即可
        for (int i = 0; i <= n; i++) {
            fastIndex = fastIndex.next;
        }
        while (fastIndex != null) {
            fastIndex = fastIndex.next;
            slowIndex = slowIndex.next;
        }

        // 此时 slowIndex 的位置就是待删除元素的前一个位置。
        // 具体情况可自己画一个链表长度为 3 的图来模拟代码来理解
        // 检查 slowIndex.next 是否为 null,以避免空指针异常
        if (slowIndex.next != null) {
            slowIndex.next = slowIndex.next.next;
        }
        return dummyNode.next;
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到