O(1)时间内删除指定链表结点
题目
给定单链表头指针和一个结点指针,定义一个函数在O(1)时间内删除该结点。
分析
对于上图实例链表(a)删除指针p有两种方式
- 思路1:(b)找到前一个指针pre,赋值pre->next = p->next,删掉p
- 思路2:(c)目的是删除p,但是不删p,直接用p->next的值赋值给p,把p->next删除掉(好处:不用遍历找到p的前一个指针pre,O(1)时间内搞定)
于是,定位到思路2,但是思路2有两个特例:
- 删除的是尾指针,需要遍历找到前一个指针
- 整个链表就一个结点(属于删尾指针,但没法找到前面的指针,需要开小灶单独处理)
大体算法思路
待删指针不是尾指针:
待删指针的值用待删指针的下一个指针的值覆盖
删掉待删指针的下一个指针
待删指针是尾指针:
待删指针同时是头指针:
删掉头指针
待删指针不是头指针
找到待删指针的前一个指针
删掉待删指针,前一个指针的next赋值为空
参考代码
bool deleteNode(ListNode *&head, ListNode *p)
{
if(!p || !head)
return false;
if(p->m_pNext != NULL) //不是尾指针
{
ListNode *del = p->m_pNext;
p->m_nValue = del->m_nValue;
p->m_pNext = del->m_pNext;
delete del;
del = NULL;
}
else if(head == p) //是尾指针,同时只有一个结点
{
delete p;
head = NULL;
}
else //是尾指针,同时有多个结点
{
ListNode *tmp = NULL, *pre = head;
while(pre->m_pNext != p)
{
pre = pre->m_pNext;
}
delete p;
p = NULL;
pre->m_pNext = NULL;
}
return true;
}
完整代码1
#include <iostream>
using namespace std; struct ListNode
{
int m_nValue;
ListNode* m_pNext;
}; bool deleteNode(ListNode *&head, ListNode *p)
{
if(!p || !head)
return false;
if(p->m_pNext != NULL)
{
ListNode *del = p->m_pNext;
p->m_nValue = del->m_nValue;
p->m_pNext = del->m_pNext;
delete del;
del = NULL;
}
else if(head == p)
{
delete p;
head = NULL;
}
else
{
ListNode *tmp = NULL, *pre = head;
while(pre->m_pNext != p)
{
pre = pre->m_pNext;
}
delete p;
p = NULL;
pre->m_pNext = NULL;
}
return true;
}
void createList(ListNode *&head)
{
head = new(ListNode);
head->m_nValue = ;
head->m_pNext = NULL; ListNode *p2 = new(ListNode);
p2->m_nValue = ;
p2->m_pNext = NULL;
head->m_pNext = p2; ListNode *p3 = new(ListNode);
p3->m_nValue = ;
p3->m_pNext = NULL;
p2->m_pNext = p3; ListNode *p4 = new(ListNode);
p4->m_nValue = ;
p4->m_pNext = NULL;
p3->m_pNext = p4;
} void deleteList(ListNode *p)
{
ListNode *next = NULL;
while(p != NULL)
{
cout << p->m_nValue << endl;
next = p->m_pNext;
delete p;
p = NULL;
p = next;
}
} int main()
{
ListNode *head = NULL;
createList(head);
ListNode *p = head->m_pNext->m_pNext->m_pNext;
deleteNode(head, p);
deleteList(head);
}
完整代码2
#include <iostream>
using namespace std; struct ListNode
{
int m_nValue;
ListNode* m_pNext;
}; bool deleteNode(ListNode **head, ListNode *p)
{
if(!p || !head)
return false;
if(p->m_pNext != NULL)
{
ListNode *del = p->m_pNext;
p->m_nValue = del->m_nValue;
p->m_pNext = del->m_pNext;
delete del;
del = NULL;
}
else if(*head == p)
{
delete p;
*head = NULL;
}
else
{
ListNode *tmp = NULL, *pre = *head;
while(pre->m_pNext != p)
{
pre = pre->m_pNext;
}
delete p;
p = NULL;
pre->m_pNext = NULL;
}
return true;
}
void createList(ListNode *&head)
{
head = new(ListNode);
head->m_nValue = ;
head->m_pNext = NULL; ListNode *p2 = new(ListNode);
p2->m_nValue = ;
p2->m_pNext = NULL;
head->m_pNext = p2; ListNode *p3 = new(ListNode);
p3->m_nValue = ;
p3->m_pNext = NULL;
p2->m_pNext = p3; ListNode *p4 = new(ListNode);
p4->m_nValue = ;
p4->m_pNext = NULL;
p3->m_pNext = p4;
} void deleteList(ListNode *p)
{
ListNode *next = NULL;
while(p != NULL)
{
cout << p->m_nValue << endl;
next = p->m_pNext;
delete p;
p = NULL;
p = next;
}
} int main()
{
ListNode *head = NULL;
createList(head);
ListNode *p = head->m_pNext->m_pNext;
deleteNode(&head, p);
deleteList(head);
}
分析
删除非尾结点时间复杂读为O(1),删除尾结点的时间复杂读为O(n), 平均时间复杂度为[(n-1)*O(1) + O(N)] / N = O(1)
还有删除函数并不能处理待删结点就是该链表中的指针,因此需要人为调用时控制,如果得验证的话,那就没必要做这些处理了,直接O(N)
技术细节——传值操作
#include <iostream>
using namespace std; struct ListNode
{
int m_nValue;
ListNode* m_pNext;
}; void createList(ListNode *head)
{
head = new(ListNode);
head->m_nValue = ;
head->m_pNext = NULL;
}
void deleteList(ListNode *p)
{
ListNode *next = NULL;
while(p != NULL)
{
cout << p->m_nValue << endl;
next = p->m_pNext;
delete p;
p = NULL;
p = next;
}
} int main()
{
ListNode *head = NULL;
createList(head);
cout << head << endl;
deleteList(head);
}
主函数中的指针head为传值调用,传到函数并没有改变主函数中的值,图示
改进的措施就是引用传值,直接操纵原指针。
O(1)时间内删除指定链表结点的更多相关文章
- 在O(1)时间内删除单链表结点
// 在O(1)时间内删除单链表结点 /* 思考: 很显然链表是一个节点地址不连续的存储结构 删除节点一般很容易会想到是修改p节点的前一个节点的next为p->next 然而除非是双向链表,否则 ...
- 在O(1)时间删除指定链表结点
#region 在O(1)时间删除指定链表结点 /// <summary> /// 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. /// </summa ...
- 在O(1)时间内删除单链表结点
给定单链表的一个结点的指针,同时该结点不是尾结点,此外没有指向其它任何结点的指针,请在O(1)时间内删除该结点. int deleteNode(LNode **head, LNode **node) ...
- 时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法
有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和 ...
- 13:在O(1)时间内删除单向链表中的一个节点
思路:如果从首部开始依次查找,那么时间是O(n). 既然我们知道要删除的结点i,那么我们就知道它指向的下一个结点j,那么我们可以将j的内容复制到i,然后将i的指针指向j的下一个结点,这样虽然看起来我们 ...
- 《剑指offer》面试题13—O(1)时间删除链表结点
题目:给定单向链表的头指针和某结点指针,实现函数在O(1)时间内删除指定节点. 思路:由于没有要删除结点(j结点)的前一个结点(i结点)指针,通常想法是从头开始遍历找到指定结点的前一个结点(i结点), ...
- pta 奇数值结点链表&&单链表结点删除
本题要求实现两个函数,分别将读入的数据存储为单链表.将链表中奇数值的结点重新组成一个新的链表.链表结点定义如下: struct ListNode { int data; ListNode *next; ...
- 【编程题目】在 O(1)时间内删除链表结点
60.在 O(1)时间内删除链表结点(链表.算法).题目:给定链表的头指针和一个结点指针,在 O(1)时间删除该结点.链表结点的定义如下:struct ListNode{int m_nKey;List ...
- (剑指Offer)面试题13:在O(1)时间内删除链表结点
题目: 在给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间内删除该结点.链表结点与函数的定义如下: struct ListNode{ int val; ListNode* next; } ...
随机推荐
- CS小分队第一阶段冲刺站立会议(5月10日)
昨日成果:完成了从excel表格导入名单,并且进行抽号的功能 遇到的困难: 1.Excel表格导入时由于版本不同,导致旧版本无法显示,后经修改初步解决 2.改程序无法在未安装office excel驱 ...
- 【BZOJ】【1047】【HAOI2007】理想的正方形
DP/单调队列优化 一眼看上去就是DP 我想的naive的二维DP是酱紫滴: mx[i][j][k]表示以(i,j)为右下角的k*k的正方形区域内的最大值,mn[i][j][k]同理 mx[i][j] ...
- 土地购买 usaco 斜率优化
看这道题的时候,感觉很难,因为数据范围比较大,很难dp: 后来想到了[书柜的尺寸]这道题,也是一道dp,曾经看了那道题的题解而深有启发: 这道题每组的付费只与这一组长宽的最大值有关,也就是说要分组,一 ...
- WPF 与Surface 2.0 SDK 亲密接触 - ScatterView 数据绑定篇
与我们常用的一些WPF 控件相同,ScatterView 控件也支持数据绑定功能.本篇将演示如何利用ScatterView 绑定Win7 系统中的样例图片,并且每张图片会以独立的ScatterView ...
- ios 环境配置网址
http://blog.csdn.net/cwb1128/article/details/18019751
- 帝国cms栏目别名如何调用?
我们在用帝国cms建站时经常会发现栏目的标题不好设置,栏目名称太长的话在后台那边看了眼花,太短又不好优化.能不能直接调用栏目别名呢?栏目别名不会什么影响.那么,帝国cms栏目别名怎么调用呢?和ytka ...
- webservice wsdl 生成服务
由于之前的示例是在当前项目下发布的server,也是在当前项目下访问的server发布的webservice.但在实际应用中,我们的服务端往往是和客户諯分离的,甚至它们是不同的项目中不同的人写的.而像 ...
- -高级Javascript编程学习笔记----Javascript编程及架构设计最应该注意的基本点
最小全局变量 JavaScript通过函数管理作用域.在函数内部生命的变量只在这个函数内部,别的地方不可用.全局变量是指在函数外或是未声明直接简单使用的.每个Javascipt环境有一个全局对象,当你 ...
- HDU4945 2048(dp)
先是看错题意..然后知道题意之后写了发dp..无限TLE..实在是不知道怎么优化了,跑了遍数据是对的,就当作理论AC掉好了.. #pragma warning(disable:4996) #inclu ...
- iOS-CALayer遮罩效果
self.view.backgroundColor = [UIColor blackColor]; , , , ); self.imageLayer.contents = (__ ...