用O(1)的时间复杂度删除单链表中的某个节点

简介: 给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下: struct ListNode { int m_nKey; ListNode* m_pNext; }; 函数的声明如下: void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted); 这是一道广为流传的Google面试题,考察我们对链表的操作和时间复杂度的了解,咋一看这道题还想不出什么较好的解法,但人家把题出在这,肯定是有解法的。

给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下:

struct ListNode
{
      int        m_nKey;
      ListNode*  m_pNext;
};

函数的声明如下:

void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted);

这是一道广为流传的Google面试题,考察我们对链表的操作和时间复杂度的了解,咋一看这道题还想不出什么较好的解法,但人家把题出在这,肯定是有解法的。一般单链表删除某个节点,需要知道删除节点的前一个节点,则需要O(n)的遍历时间,显然常规思路是不行的。在仔细看题目,换一种思路,既然不能在O(1)得到删除节点的前一个元素,但我们可以轻松得到后一个元素,这样,我们何不把后一个元素赋值给待删除节点,这样也就相当于是删除了当前元素。可见,该方法可行,但如果待删除节点为最后一个节点,则不能按照以上思路,没有办法,只能按照常规方法遍历,时间复杂度为O(n),是不是不符合题目要求呢?可能很多人在这就会怀疑自己的思考,从而放弃这种思路,最后可能放弃这道题,这就是这道面试题有意思的地方,虽看简单,但是考察了大家的分析判断能力,是否拥有强大的心理,充分自信。其实我们分析一下,仍然是满足题目要求的,如果删除节点为前面的n-1个节点,则时间复杂度为O(1),只有删除节点为最后一个时,时间复杂度才为O(n),所以平均的时间复杂度为:(O(1) * (n-1) + O(n))/n = O(1);仍然为O(1).下面见代码:

 1 /* Delete a node in a list with O(1)
 2  * input:    pListHead - the head of list
 3  *            pToBeDeleted - the node to be deleted
 4  */
 5 
 6 struct  ListNode  
 7 {
 8     int            m_nKey;
 9     ListNode*    m_pNext;
10 };
11 
12 void DeleteNode(ListNode *pListHead, ListNode *pToBeDeleted)
13 {
14     if (!pListHead || !pToBeDeleted)
15         return;
16     
17     if (pToBeDeleted->m_pNext != NULL) { 
18         ListNode *pNext = pToBeDeleted->m_pNext;
19         pToBeDeleted->m_pNext = pNext->m_pNext;
20         pToBeDeleted->m_nKey = pNext->m_nKey;
21 
22         delete pNext;
23         pNext = NULL;
24     }
25     else { //待删除节点为尾节点
26         ListNode *pTemp = pListHead;
27         while(pTemp->m_pNext != pToBeDeleted) 
28             pTemp = pTemp->m_pNext;
29         pTemp->m_pNext = NULL;
30 
31         delete pToBeDeleted;
32         pToBeDeleted = NULL;
33     }
34 }

 

目录
相关文章
|
存储 弹性计算 监控
解密EDAS新一代应用发布系统
本文针对 企业级分布式应用服务( EDAS ) 应用生命周期管理所使用的发布单系统进行介绍,包括背景、设计目标、设计方案、功能介绍等,新开发的发布单系统实现了变更过程的流程化、任务化、可视化,发布流程可定制,支持多种变更策略,自2017年8月上线以来,承担着 EDAS 生命周期管理操作。
6456 0
Vue2开关(Switch)
这是一个基于 Vue3 的开关(Switch)组件,支持多种自定义属性:初始选中状态 (`defaultChecked`)、选中与未选中时显示的内容 (`checkedInfo`, `uncheckedInfo`)、是否禁用 (`disabled`) 及双向绑定 (`v-model`) 控制选中状态 (`checked`)。通过简单配置即可实现功能丰富的开关控件。
341 0
Vue2开关(Switch)
|
存储 物联网 Serverless
玩转 AI 绘图,基于函数计算部署 Stable Diffusion可自定义模型
本文主要将带大家通过使用阿里云产品函数计算 FC 和文件存储 NAS ,快速使用 Stable Diffusion 实现更高质量的图像生成,本方案内置模型库+常用插件+ControlNet ,用户可根据自己的需要更换需要的模型、Lora、增加插件。
69326 27
玩转 AI 绘图,基于函数计算部署 Stable Diffusion可自定义模型
ly~
|
供应链 搜索推荐 大数据
大数据在零售业中的应用
在零售业中,大数据通过分析顾客的购买记录、在线浏览习惯等数据,帮助零售商理解顾客行为并提供个性化服务。例如,分析网站点击路径以了解顾客兴趣,并利用历史购买数据开发智能推荐系统,提升销售和顾客满意度。此外,大数据还能优化库存管理,通过分析销售数据和市场需求,更准确地预测需求,减少库存积压和缺货现象,提高资金流动性。
ly~
1077 2
|
人工智能 自然语言处理 API
如何使用ModelScope-Agent快速搭建一个火爆全网的哄哄模拟器
前不久,一个爆火的基于大语言模型的应用“哄哄模拟器”在QQ群爆火了,通过文字聊天的方式,模拟在各种吵架场景中如果哄好女友,女友是由AI扮演,包含了数值系统和虚拟伴侣的文本对话能力。
|
资源调度 Kubernetes 监控
Kubernetes 集群性能优化实践
【5月更文挑战第17天】在容器化和微服务架构日益普及的当下,Kubernetes 已成为众多企业的首选容器编排工具。然而,随着集群规模的增长和业务复杂度的提升,性能优化成为确保系统稳定性与高效运行的关键。本文将深入探讨 Kubernetes 集群性能优化的策略与实践,覆盖从节点资源配置到网络通信优化,再到高效的资源调度机制,旨在为运维人员提供系统的优化路径和具体的操作建议。
|
缓存 前端开发 Java
DolphinScheduler教程(04)- 项目配置分析
DolphinScheduler教程(04)- 项目配置分析
901 0
|
芯片
clock oscillator,generator,buffer选型杂谈
clock oscillator,generator,buffer选型杂谈
472 0
|
存储 关系型数据库 OLAP
PostgreSQL 列存, 混合存储, 列存索引, 向量化存储, 混合索引 - OLTP OLAP OLXP HTAP 混合负载应用
PostgreSQL 列存, 混合存储, 列存索引, 向量化存储, 混合索引 - OLTP OLAP OLXP HTAP 混合负载应用
5854 0

热门文章

最新文章