题目描述
// 力扣
// 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
// 返回删除后的链表的头节点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
题解
// 双指针法 //
// 对数据结构有印象的就知道,删除一个链表结点,需要找待删除结点的前一个结点
// 令前一个结点直接指向待删除结点的next,这个待删除结点就从链表结构中被去除了。
// 执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
// 内存消耗:37.9 MB, 在所有 Java 提交中击败了71.42%的用户
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if (head == null)
return null;
// 假定val是一定找得到的,head.next不存在,那待删除结点是head本身,删除后返回null
if (head.next == null)
return null;
// 如果待删除节点是头结点,直接返回head.next
if (head.val == val && head.next != null)
return head.next;
// new一个链表引用pre,它的next指向head,即head前面多了一个节点
// 这个引用指针用来遍历待删除节点的前一个结点
ListNode pre = new ListNode(0); // pre.val初始化为0(无影响)
pre.next = head;
// 定义链表引用cur,它直接指向head,
// 这个引用指针用于遍历整个链表
ListNode cur = head;
while (cur != null) {
// 非尾结点
// 若cur指针找到了val所在的结点
if (cur.val == val && cur.next != null) {
// 令pre.next直接越过待删除结点cur
// 直接指向cur的下一个结点cur.next
pre.next = cur.next;
cur = null; // 规范操作,令cur元素清空
break;
}
// 尾结点
if (cur.val == val && cur.next == null) {
pre.next = null; // 直接令pre.next指向null
break;
}
pre = pre.next; // 没找到val,右移一位
cur = cur.next; // 没找到val,右移一位
}
return head; // 题目要求返回删除后的链表,返回头引用即可
}
}
// 递归法 //
class Solution {
// 解题函数,也是递归函数
// 递归函数检查head.next是否为待删除结点
public ListNode deleteNode(ListNode head, int val) {
// 以下三个if语句跟双指针法是一样的,但是意义不一样
// 若head第一个结点就不存在,返回null
if (head == null)
return null;
// 1.当deleteNode还没被递归调用时:
// 此时head还指向头结点,如果head.next为null,说明整个链表就一个结点,删除之后为null
// 2.当deleteNode被递归调用后:
// 由于递归调用的语句是head.next = deleteNode(head.next, val);
// 因此字段head实际表示head.next,那字段head.next实际表示head.next.next,
// 若head.next.next为null,说明head.next是待删除尾结点,直接返回null,
// 这时候head.next会被指向这个返回的null,删除完成
// (注:如果这句if能触发,说明在head.next到达尾结点之前一直都没return过
// 说明尾结点必为待删除结点)
if (head.next == null)
return null;
// 1.当deleteNode还没被递归调用时:
// 如果待删除节点是头结点,直接返回head.next
// 2.当deleteNode被递归调用后:
// head实际表示head.next,所以如果head.next.val == val
// 说明head.next是待删除结点,返回head.next,也就是返回
// head.next.next,这时head.next会指向这个返回的head.next.next
// 原来的head.next从链表中被移除。
if (head.val == val && head.next != null)
return head.next;
// 将head.next指向deleteNode的返回值
// deleteNode将被递归调用,输入为head.next和val
head.next = deleteNode(head.next, val);
// 递归完成,返回删除好的链表头索引head
return head;
}
}