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)官网 - 全球极客挚爱的技术成长平台

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/354053.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PINN物理信息网络 | 全局自适应物理信息神经网络SA-PINN

概述 本文提出的自适应加权方法在于权重适用于不同损失组件中的个别训练点,而不是整个损失组件。之前的方法可以被看作是这个方法的一个特例,当所有针对特定损失组件的自适应权重同时更新时。在之前的方法中,独立开发的极小极大加权方案[16]与SA-PINNs最为相近,因为它也通过…

SpringCloud--FeignGateWay

Feign 创建项目勾选web SpringWeb 1.0 创建生产者SpringCloudFeignProvider 端口号:8081 pom.xml引入依赖 <!--nacos依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery<…

语义分割(3):损失函数解析

文章目录 1. 常见语义分割损失1.1 Cross Entropy1.2 dice Loss1.2.1 为什么使用Dice loss1.2.2 公式1.2.3 Dice loss 和 F1-score代码 1.3 focal loss1.3.1 公式&#xff1a;1.3.2 代码 2. 语义分割损失应用参考 语义分割任务实际上是一种像素层面上的分类&#xff0c;需要识别…

回归预测 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多输入单输出回归预测

回归预测 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多输入单输出回归预测 目录 回归预测 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多输入单输出回归预测预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab基于SSA-SVR麻雀算法优化支持向量机的数据…

Qlik Sense 使用Join合并表格

Join | Windows 版 Qlik Sense帮助 什么是Qlik Sense的Join join 前缀可连接加载的表格和现有已命名的表格或最近创建的数据表。本质上跟SQL的Join很类似。 联接数据的效果是通过一组额外的字段或属性扩展目标表&#xff0c;即目标表中不存在的字段或特性。源数据集和目标表之间…

牛客——只能吃土豆的牛牛(进制转化)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 旅行完了的牛牛又胖了&#xff0c;于是他终于下决心要戒掉零食&#xff0c;所以他带着他最爱的土豆回到了牛星&#xff0c;开始了在牛星种土豆和只吃土豆减肥的日子。&#xff08;吃土豆能减肥…

Future模式先给您提货单

Future模式是一种设计模式&#xff0c;用于在处理耗时操作时提高程序的响应性。 角色介绍: Main类: 负责向Host发出请求并获取数据的类。 Host类: 负责向请求返回FutureData的实例的类&#xff0c;起到调度的作用。 Data接口: 表示访问数据的方法的接口&#xff0c;由FutureD…

S275智慧煤矿4G物联网网关:矿山开采的未来已来

随着经济发展煤矿需求不断激增&#xff0c;矿山矿井普遍处于偏远山区&#xff0c;生产管理、人员安全、生产效率是每个矿山矿井都需要考虑的问题&#xff0c;利用网关对现场终端设备连接组网&#xff0c;实现智慧煤矿远程管理。 各矿山矿井分布范围比较广泛&#xff0c;户外环…

python内置函数有哪些?整理到了7大分类48个函数,都是工作中常用的函数

python内置函数 一、入门函数 1.input() 功能&#xff1a; 接受标准输入&#xff0c;返回字符串类型 语法格式&#xff1a; input([提示信息])实例&#xff1a; # input 函数介绍text input("请输入信息:") print("收到的数据是:%s" % (text))#输出…

Qt Design Studio+Pyside项目

Qt Design Studio设计出的项目结构有多个层级的目录&#xff0c;我们直接用类似Qt Creator工具的方式加载main.qml文件时会报错提示module "content" is not installed&#xff0c;将content加入importPath后还是报同样的错误。 Qt Design Studio生成的文件包含了.qm…

lv14 内核内存管理、动态分频及IO访问 12

一、内核内存管理框架 内核将物理内存等分成N块4KB&#xff0c;称之为一页&#xff0c;每页都用一个struct page来表示&#xff0c;采用伙伴关系算法维护 补充&#xff1a; Linux内存管理采用了虚拟内存机制&#xff0c;这个机制可以在内存有限的情况下提供更多可用的内存空…

路由、组件目录存放

文章目录 单页应用程序&#xff1a;SPA- Single Page Application路由的介绍VuePouter的介绍VueRouted 的使用 组件目录存放问题&#xff08;组件分类&#xff09; 单页应用程序&#xff1a;SPA- Single Page Application 单页应用&#xff08;SPA&#xff09;:所有功能在一个…

Springmvc-@RequestBody

SpringBoot-2.7.12 请求的body参数无法转换&#xff0c;服务端没有报错信息打印&#xff0c;而是响应的状态码是400 PostMapping("/static/user") public User userInfo(RequestBody(required false) User user){user.setAge(19);return user; }PostMapping("…

算法设计与分析实验一:二分查找

目录 一、有序数组中的单一元素 1.1思路 1.2 代码实现 1.3 运行结果 二、长度最小的子数组 2.1思路 2.2 代码 2.3 运行结果 三、 山脉数组中查找目标值 3.1 思路 3.2 代码 3.3 运行结果 四、寻找旋转排序数组中的最小值 4.1思路 4.2代码 4.3 运行结果 一、有…

超越 Node.js:Bun 的创新与突破

1. Bun Bun 是一个全新的 JavaScript 运行时&#xff0c;类似于 Node.js 和 Deno&#xff0c;它专注于提供出色的性能和开发者体验。Bun 的一些特点包括&#xff1a; 快速的性能&#xff1a;Bun 旨在提供高性能&#xff0c;无论是启动时间、执行速度还是安装依赖包的速度。 兼…

ORM-02-Hibernate 对象关系映射(ORM)框架

拓展阅读 The jdbc pool for java.(java 手写 jdbc 数据库连接池实现) The simple mybatis.&#xff08;手写简易版 mybatis&#xff09; Hibernate Hibernate ORM 允许开发者更轻松地编写那些数据在应用程序进程结束后仍然存在的应用程序。 作为一个对象关系映射&#xff08…

蓝桥杯省赛无忧 编程14 肖恩的投球游戏加强版

#include <stdio.h> #define MAX_N 1003 int a[MAX_N][MAX_N], d[MAX_N][MAX_N]; // 差分数组的初始化 void init_diff(int n, int m) {for (int i 1; i < n; i) {for (int j 1; j < m; j) {d[i][j] a[i][j] - a[i-1][j] - a[i][j-1] a[i-1][j-1];}} } // 对差…

【王道数据结构】【chapter2线性表】【P44t17~t20】【统考真题】

目录 2009年统考 2012年统考 2015年统考 2019年统考 2009年统考 #include <iostream>typedef struct node{int data;node* next; }node,*list;list Init() {list head(list) malloc(sizeof (node));head->next nullptr;head->data-1;return head; }list Buyne…

QA-GNN: 使用语言模型和知识图谱的推理问答

Abstract 使用预训练语言模型&#xff08;LMs&#xff09;和知识图谱&#xff08;KGs&#xff09;的知识回答问题的问题涉及两个挑战&#xff1a;在给定的问答上下文&#xff08;问题和答案选择&#xff09;中&#xff0c;方法需要&#xff08;i&#xff09;从大型知识图谱中识…

C++:auto 关键字 范围for

目录 auto 关键字&#xff1a; 起源&#xff1a; auto的使用细则&#xff1a; auto不能推导的场景&#xff1a; 范围for&#xff1a; 范围for的使用条件&#xff1a; C的空指针&#xff1a; 注意&#xff1a; auto 关键字&#xff1a; 起源&#xff1a; 随着程序越…