面试题18. 删除链表的节点

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。

返回删除后的链表的头节点。

输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    class Solution:
    def deleteNode(self, head: ListNode, val: int) -> ListNode:
        dummy = ListNode(0)  # 设置伪结点
        dummy.next = head
        if head.val == val: return head.next # 头结点是要删除的点,直接返回
        while head and head.next:
            if head.next.val == val:   # 找到了要删除的结点,删除
                head.next = head.next.next
            head = head.next
        return dummy.next

val为int时解法:信息交换法

假如 head 为 4 -> 5 -> 1 -> 9,val 为 5 -> 1 -> 9,表示我们要删除结点 5,这时我们使用信息交换,把 val 改为 1 -> 9的信息就行了。

为什么呢?因为我们把待删除节点的后一个元素赋值给待删除节点,也就相当于删除了当前元素。

但是聪明的你一定会举出反例:如果 val 的值是最后一个元素 9 呢?我们无法找到 9 的后一个元素(因为没有),只能重头开始找待删除元素 9,这样的话时间复杂度再次变成了 O(N)。

这就是这道题目有意思的地方,我们发现,如果删除节点为前面的 n−1个节点,时间复杂度均为 O(1),只有删除节点为最后一个时,时间复杂度才会变成 O(n)。平均时间复杂度为: ( O ( 1 ) × ( n 1 ) + O ( n ) ) / n = O ( 1 ) (O(1)×(n−1)+O(n))/n=O(1) ,仍然为 O(1)。

class Solution:
    def deleteNode(self, head, val):
        if head is None or val is None:
            return None
        if val.next is not None:  # 待删除节点不是尾节点
            tmp = val.next
            val.val = tmp.val
            val.next = tmp.next
        elif head == val:  # 待删除节点只有一个节点,此节点为头节点
            head = None
        else:
            cur = head    # 待删除节点为尾节点
            while cur.next != val:
                cur = cur.next
            cur.next = None
        return head

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shan-chu-lian-biao-de-jie-dian-lcof

发布了88 篇原创文章 · 获赞 31 · 访问量 5074

猜你喜欢

转载自blog.csdn.net/weixin_43455338/article/details/104880012