【每天学习一点算法 2025/12/09】删除链表节点

每天学习一点算法 2025/12/09

题目:删除链表中的节点

有一个单链表的 head,我们想删除它其中的一个节点 node。

给你一个需要删除的节点 node 。你将 无法访问 第一个节点 head。

链表的所有值都是 唯一的,并且保证给定的节点 node 不是链表中的最后一个节点。

删除给定的节点。注意,删除节点并不是指从内存中删除它。这里的意思是:

给定节点的值不应该存在于链表中。

链表中的节点数应该减少 1。

node 前面的所有值顺序相同。

node 后面的所有值顺序相同。

自定义测试:

对于输入,你应该提供整个链表 head 和要给出的节点 node。node 不应该是链表的最后一个节点,而应该是链表中的一个实际节点。

我们将构建链表,并将节点传递给你的函数。

输出将是调用你函数后的整个链表。

这个问题很简单,将节点的 valnext 修改为下一个节点的 valnext 即可。

function deleteNode(node: ListNode | null): void {
  if (node?.next) {
    node.val = node?.next?.val
    node.next = node?.next?.next
  }
};

这个太简单了,再来一道

题目:删除链表的倒数第N个节点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

  1. 要找到倒数第 n 个节点就必须知道链表的长度,我们可以先遍历一次链表获取长度,这样我就可以知道倒数第 n 个节点具体是哪一个了。

    function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
      if (!head || n <= 0) {
        return head;
      }
    
      let len = 0
      let cur: ListNode | null  = head
      // 遍历链表获取长度
      while (cur) {
        len++
        cur = cur.next
      }
      cur = head
      // 找到需要删除 node 的上一个几点执行删除操作
      if (len === n) {
        if (head?.next) {
          head.val = head.next?.val
          head.next = head.next?.next || null
        } else {
          head = null
        }
      } else {
        for (let i = 0; i < len - n - 1; i++) {
          cur = cur?.next || null
        }
        if (cur?.next) {
          cur.next = cur?.next?.next
        }
      }
      return head
    };
    
  2. 我们还可以用一个栈来存储链表的节点,弹出是计数即可找到需要删除的节点。

    function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
      if (!head || n <= 0) {
        return head;
      }
    
      const stack: ListNode[] = []
      let cur: ListNode | null = head
      // 所有节点压栈
      while (cur) {
        stack.push(cur)
        cur = cur.next
      }
      // 弹出 n 个节点
      for (let i = 0; i < n; i++) {
        stack.pop()
      }
      // 此时栈顶的节点就是第n个节点的上一个节点
      if (stack.length === 0) {
        head = head.next || null
      } else {
        const prev = stack[stack.length - 1]
        prev.next = prev.next?.next || null
      }
      return head
    }
    
  3. 还可以使用快慢指针的方法,快指针先移动到第 n 个节点处,然后快慢指针一起移动,等到快指针到链表尾部时,慢指针指向就是倒数第 n 个节点的上一个节点,执行删除操作即可。

    function removeNthFromEnd2(head: ListNode | null, n: number): ListNode | null {
      if (!head || n <= 0) {
        return head;
      }
    
      let fast: ListNode | null = head
      let slow: ListNode | null = head
      // 快指针移动到第n个节点
      for (let i = 0; i < n; i++) {
        fast = fast?.next || null
      }
      if (!fast) {
        // fast如果是null n等于链表长度,删除head
        head = head.next || null
      } else {
        // 同时移动快慢指针直到快指针为null
        while (fast?.next) {
          fast = fast.next
          slow = slow?.next || null
        }
        slow?.next && (slow.next = slow.next.next)
      }
      return head
    }
    

每天学习一点算法 2025/12/09

题目:删除链表中的节点

有一个单链表的 head,我们想删除它其中的一个节点 node。

给你一个需要删除的节点 node 。你将 无法访问 第一个节点 head。

链表的所有值都是 唯一的,并且保证给定的节点 node 不是链表中的最后一个节点。

删除给定的节点。注意,删除节点并不是指从内存中删除它。这里的意思是:

给定节点的值不应该存在于链表中。

链表中的节点数应该减少 1。

node 前面的所有值顺序相同。

node 后面的所有值顺序相同。

自定义测试:

对于输入,你应该提供整个链表 head 和要给出的节点 node。node 不应该是链表的最后一个节点,而应该是链表中的一个实际节点。

我们将构建链表,并将节点传递给你的函数。

输出将是调用你函数后的整个链表。

这个问题很简单,将节点的 valnext 修改为下一个节点的 valnext 即可。

function deleteNode(node: ListNode | null): void {
  if (node?.next) {
    node.val = node?.next?.val
    node.next = node?.next?.next
  }
};

这个太简单了,再来一道

题目:删除链表的倒数第N个节点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

  1. 要找到倒数第 n 个节点就必须知道链表的长度,我们可以先遍历一次链表获取长度,这样我就可以知道倒数第 n 个节点具体是哪一个了。

    function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
      if (!head || n <= 0) {
        return head;
      }
    
      let len = 0
      let cur: ListNode | null  = head
      // 遍历链表获取长度
      while (cur) {
        len++
        cur = cur.next
      }
      cur = head
      // 找到需要删除 node 的上一个几点执行删除操作
      if (len === n) {
        if (head?.next) {
          head.val = head.next?.val
          head.next = head.next?.next || null
        } else {
          head = null
        }
      } else {
        for (let i = 0; i < len - n - 1; i++) {
          cur = cur?.next || null
        }
        if (cur?.next) {
          cur.next = cur?.next?.next
        }
      }
      return head
    };
    
  2. 我们还可以用一个栈来存储链表的节点,弹出是计数即可找到需要删除的节点。

    function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
      if (!head || n <= 0) {
        return head;
      }
    
      const stack: ListNode[] = []
      let cur: ListNode | null = head
      // 所有节点压栈
      while (cur) {
        stack.push(cur)
        cur = cur.next
      }
      // 弹出 n 个节点
      for (let i = 0; i < n; i++) {
        stack.pop()
      }
      // 此时栈顶的节点就是第n个节点的上一个节点
      if (stack.length === 0) {
        head = head.next || null
      } else {
        const prev = stack[stack.length - 1]
        prev.next = prev.next?.next || null
      }
      return head
    }
    
  3. 还可以使用快慢指针的方法,快指针先移动到第 n 个节点处,然后快慢指针一起移动,等到快指针到链表尾部时,慢指针指向就是倒数第 n 个节点的上一个节点,执行删除操作即可。

    function removeNthFromEnd2(head: ListNode | null, n: number): ListNode | null {
      if (!head || n <= 0) {
        return head;
      }
    
      let fast: ListNode | null = head
      let slow: ListNode | null = head
      // 快指针移动到第n个节点
      for (let i = 0; i < n; i++) {
        fast = fast?.next || null
      }
      if (!fast) {
        // fast如果是null n等于链表长度,删除head
        head = head.next || null
      } else {
        // 同时移动快慢指针直到快指针为null
        while (fast?.next) {
          fast = fast.next
          slow = slow?.next || null
        }
        slow?.next && (slow.next = slow.next.next)
      }
      return head
    }
    

题目来源:力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值