当先锋百科网

首页 1 2 3 4 5 6 7

题目描述

在这里插入图片描述

// 力扣
// 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
// 返回删除后的链表的头节点。
/**
 * 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;
	}
}