python_ACM模式《剑指offer刷题》链表3

题目:

注意:

剑指offer上对这道题目的描述是给定的删除节点是节点指针。这表明这道题可以用时间复杂度为O(1)的方式解决。

而leetcode上对类似本题的描述是:

给定删除节点是节点值,这决定了本题时间复杂度必然至少为O(N)。因为必定要从头遍历链表。

          

面试tips:

1. 注意以上两种问法的区别。若是第一种,最优的方式时复为O(1)。

2. 这道题默认了所给的删除节点就在链表上,可以跟面试官提一下,显示对此考虑的更全面。如果不在还要进行判断。

思路:

这里实现剑指offer上的问法,leetcode上的采用这里的思路一很容易解决。

1. 遍历一遍链表,找到要删除的节点的前一个节点,进行删除操作即可。

2. 如果给定的删除节点是一个节点指针(该指针指向待删除链表的某一个节点),则可不需从头遍历就已经知道了要删除的节点的位置,只是不知道其前一个位置。事实上,由下面步骤我们可知,只要给的是要删除节点的指针,则可以不需要知道其前一个位置也可进行删除。

①设置虚拟节点,使得若删除的是头节点,下面的操作都相同。

②若要删除的不是尾节点,则将要删除的节点深拷贝其下一个节点,将下一个节点进行删除(因为知道当前节点就是下一个节点的前一个节点,因此很容易删除),虽然不是真正删除所删除的节点,但因为深拷贝,也就等价于是删除掉所删除的节点的结果了。见下图的c。

③若删除的是尾节点,因为一个正常节点是不能够深拷贝为空节点的,因此②走不通,这时只能从头遍历了,找到尾节点的前一个节点进行删除。

总的平均时间复杂度:((n-1)* O(1) + 1 * O(n) )  /  n  -> O(1)

代码实现:

1和2的代码实现上更改的部分只有class solution部分,其余部分是根据数组构建单链表及要删除的节点指针。

1.

class ListNode:
    def __init__(self, val = 0, next = None):
        self.val = val
        self.next = next

def arr2List(arr, val):
    # 一维数组转单链表, 同时对应值要找到对应节点
    # 设置虚拟头节点,使得对头节点的操作同
    prev = dummy_head = ListNode()
    for i in range(len(arr)):
        tmp = ListNode(val = arr[i])
        prev.next = tmp
        prev = prev.next
        if arr[i] == val:
            tod_Node = tmp
    return dummy_head.next, tod_Node

def List2arr(head):
    # 单链表转一维数组
    curr = head
    arr = []
    while curr:
        arr.append(curr.val)
        curr = curr.next
    return arr

class Solution:
    def deleteNode(self, head, tod_Node):
        # 从头遍历找到对应的节点
        prev = dummy_head = ListNode(next = head)
        while prev.next:
            if prev.next == tod_Node:
                prev.next = prev.next.next
                return head
            else:
                prev = prev.next

if __name__ == '__main__':
    # 若给定一维数组,及要删除的节点值
    arr = [4, 5, 1, 9]
    val = 9  # 这里表明要删除的节点为5所对应的节点
    # 先要将其转为单链表以及相应节点
    head, tod_Node= arr2List(arr, val)
    a = Solution()
    new_head = a.deleteNode(head, tod_Node)
    new_arr = List2arr(new_head)
    print(new_arr)

2.

class ListNode:
    def __init__(self, val = 0, next = None):
        self.val = val
        self.next = next

def arr2List(arr, val):
    # 一维数组转单链表, 同时对应值要找到对应节点
    # 设置虚拟头节点,使得对头节点的操作同
    prev = dummy_head = ListNode()
    for i in range(len(arr)):
        tmp = ListNode(val = arr[i])
        prev.next = tmp
        prev = prev.next
        if arr[i] == val:
            tod_Node = tmp
    return dummy_head.next, tod_Node

def List2arr(head):
    # 单链表转一维数组
    curr = head
    arr = []
    while curr:
        arr.append(curr.val)
        curr = curr.next
    return arr

class Solution:
    def deleteNode(self, head, tod_Node):
        # 1. 为确保头节点操作与其余节点同,设置一个虚拟头节点
        # 2. 若删除的节点不是最后一个节点,则将其下一个节点复制过来,删除下一个节点,这等价于删除当前节点
        # 3. 若删除的节点是最后一个节点,则下一个节点为空是无法复制的,因此这是需从头节点遍历找到最后一个的前一个节点进行删除操作
        dummy_head = ListNode(0,next = head)
        if tod_Node.next != None:
            # 则说明要删除的节点不是最后一个节点
            # 深拷贝下一个节点至当前节点 并同时也将下一个节点删除了
            tod_Node.val = tod_Node.next.val
            tod_Node.next = tod_Node.next.next
            return head
        else:
            # 此时要删除的节点是最后一个节点,同时其也有可能是第一个节点(但是因为有虚拟头节点在 因此不可能为真正意义上的第一个节点)
            # 因为该节点不可能从不空变为空(深拷贝意义上的空) 因此只能从头节点开始遍历
            prev = dummy_head
            while prev.next:
                if prev.next == tod_Node:
                    prev.next = prev.next.next
                    return head
                else:
                    prev = prev.next

if __name__ == '__main__':
    # 若给定一维数组,及要删除的节点值
    arr = [4, 5, 1, 9]
    val = 1  # 这里表明要删除的节点为5所对应的节点
    # 先要将其转为单链表以及相应节点
    head, tod_Node= arr2List(arr, val)
    a = Solution()
    new_head = a.deleteNode(head, tod_Node)
    new_arr = List2arr(new_head)
    print(new_arr)

参考:

1.《剑指offer》

2. 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

相关推荐

  1. Offer(第2版)面试 24:反转

    2024-01-28 18:50:02       45 阅读
  2. offer面试13 在O(1)时间删除结点

    2024-01-28 18:50:02       38 阅读
  3. 牛客offer其他算法篇

    2024-01-28 18:50:02       28 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-28 18:50:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-28 18:50:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-28 18:50:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-28 18:50:02       18 阅读

热门阅读

  1. QT笔记 - QToolButton triggered(QAction *)不触发问题

    2024-01-28 18:50:02       33 阅读
  2. 初识C语言

    2024-01-28 18:50:02       41 阅读
  3. go 面试题分享

    2024-01-28 18:50:02       26 阅读
  4. 运维文本三剑客详辨

    2024-01-28 18:50:02       28 阅读
  5. Linux delay相关函数实现

    2024-01-28 18:50:02       25 阅读
  6. 无人机调试开源软件

    2024-01-28 18:50:02       45 阅读
  7. Writing and Using a Simple Plugin

    2024-01-28 18:50:02       34 阅读
  8. 电脑上显示U盘多个盘符怎么办?

    2024-01-28 18:50:02       42 阅读