【题目】

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

struct ListNode

{

int        value;

struct ListNode*  next;

};

函数的声明例如以下:

void DeleteNode(ListNode* head,ListNode* node);

【思路】

这是一道广为流传的Google面试题,能有效考察我们的编程基本功,还能考察我们的反应速度,更重要的是,还能考察我们对时间复杂度的理解。

在链表中删除一个结点,最常规的做法是从链表的头结点開始,顺序查找要删除的结点,找到之后再删除。因为须要顺序查找,时间复杂度自然就是O(n) 了。

我们之所以须要从头结点開始查找要删除的结点。是由于我们须要得到要删除的结点的前面一个结点。

我们试着换一种思路。我们能够从给定的结点得到它的下一个结点。

这个时候我们实际删除的是它的下一个结点。由于我们已经得到实际删除的结点的前面一个结点,因此全然是能够实现的。

当然。在删除之前。我们须要须要把给定的结点的下一个结点的数据复制到给定的结点中。此时。时间复杂度为O(1)。

上面的思路另一个问题:假设删除的结点位于链表的尾部,没有下一个结点。怎么办?我们仍然从链表的头结点開始,顺便遍历得到给定结点的前序结点,并完毕删除操作。这个时候时间复杂度是O(n)。

那题目要求我们须要在O(1)时间完毕删除操作,我们的算法是不是不符合要求?实际上,如果链表总共同拥有n个结点,我们的算法在n-1总情况下时间复杂度是O(1)。仅仅有当给定的结点处于链表末尾的时候,时间复杂度为O(n)。那么平均时间复杂度[(n-1)*O(1)+O(n)]/n,仍然为O(1)。

基于前面的分析。我们不难写出以下的代码。

/*********************************
* 日期:2014-10-29
* 作者:SJF0115
* 题目: 给定链表的头指针和一个结点指针,在O(1)时间删除该结点
* 来源:经典面试题
* 总结:
**********************************/
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std; struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
//O(1)时间 删除链表中的节点
void DeleteNode(ListNode** head,ListNode* node){
if(head == NULL || node == NULL){
return;
}
ListNode* p = node->next;
// 删除的不是末尾节点 O(1)
if(p != NULL){
//删除p节点
node->next = p->next;
// 节点p拷贝到node节点
node->next = p->next;
node->val = p->val;
delete p;
p = NULL;
}
// 删除的是末尾节点 O(n)
else{
ListNode* pre = *head;
// 末尾节点
while(pre->next != node){
pre = pre->next;
}
//删除node节点
pre->next = NULL;
delete node;
node = NULL;
}
} int main() {
ListNode* node1 = new ListNode(1);
ListNode* node2 = new ListNode(2);
ListNode* node3 = new ListNode(3);
ListNode* node4 = new ListNode(4);
ListNode* node5 = new ListNode(5); node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = node5; //无头结点链表
DeleteNode(&node1,node2); while(node1 != NULL){
printf("%d ",node1->val);
node1 = node1->next;
}
return 0;
}

何海涛:

值得注意的是。为了让代码看起来简洁一些,上面的代码基于两个如果:(1)给定的结点的确在链表中。(2)给定的要删除的结点不是链表的头结点。不考虑第一个如果对代码的鲁棒性是有影响的。

至于第二个如果,当整个列表仅仅有一个结点时,代码会有问题。但这个如果不算非常过分。由于在有些链表的实现中。会创建一个虚拟的链表头,并非一个实际的链表结点。

这样要删除的结点就不可能是链表的头结点了。当然,在面试中,我们能够把这些如果和面试官交流。这样,面试官还是会认为我们考虑问题非常周到的。

[经典面试题]在O(1)时间删除链表结点的更多相关文章

  1. 《剑指offer》面试题13—O(1)时间删除链表结点

    题目:给定单向链表的头指针和某结点指针,实现函数在O(1)时间内删除指定节点. 思路:由于没有要删除结点(j结点)的前一个结点(i结点)指针,通常想法是从头开始遍历找到指定结点的前一个结点(i结点), ...

  2. 【面试题013】在O(1)时间删除链表结点

    [面试题013]在O(1)时间删除链表结点  我们要删除结点i,我们可以把结点i的下一个结点j的内容复制到结点i,然后呢把结点i的指针指向结点j的下一个结点.然后在删除结点j. 1.如果结点i位于链表 ...

  3. 面试题18(一):在O(1)时间删除链表结点

    // 面试题18(一):在O(1)时间删除链表结点 // 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该 // 结点.链表结点与函数的定义如下: // struct Lis ...

  4. 剑指Offer面试题:12.在O(1)时间删除链表结点

    一.题目:在O(1)时间删除链表结点 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. 原文采用的是C/C++,这里采用C#,节点定义如下: public class ...

  5. 【Java】 剑指offer(17) 在O(1)时间删除链表结点

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除 ...

  6. 《剑指offer》第十八题(在O(1)时间删除链表结点)

    // 面试题18(一):在O(1)时间删除链表结点 // 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该 // 结点. #include <iostream> ...

  7. 第18题:在O(1)时间删除链表结点+删除链表中重复的节点

    题目描述:题目描述在O(1)时间删除链表结点 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. 考查创新编程能力. 思路: 1.如果从头到尾遍历,时间O(n) 2.如果将待删 ...

  8. 程序员面试题精选100题(33)-在O(1)时间删除链表结点[数据结构]

    作者:何海涛 出处:http://zhedahht.blog.163.com/ 题目:给定链表的头指针和一个结点指针,在O(1)时间删除该结点.链表结点的定义如下: struct ListNode { ...

  9. 剑指Offer:面试题13——在O(1)时间删除链表结点

    问题描述: 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点.链表结点与函数的定义如下: public class ListNode{ int value; ListNode ...

随机推荐

  1. 定位 absolute和relative比较

    absolute:脱离原来位置定位.是相对于最近的有定位的父级进行定位;如果没有有定位的父级元素,就相对文档进行定位 relative:保留原来位置进行定位,相对于自己原来的位置进行定位 下面举两个例 ...

  2. poj1681 Painter's Problem

    题目描述: 和那道关灯差不多,求最少涂几次. 题解: 高消,然后深搜枚举自由元更新答案. 貌似这道题没卡贪心但是其他题基本都卡了. 比如$Usaco09Nov$的$lights$ 代码: #inclu ...

  3. MySQL教程之存储过程与函数

    存储程序分为存储过程和函数 可以使用CALL来调用存储过程,只能输出变量返回值.存储过程可以调用其他存储过程 函数可以从语句外调用,也能返回标量值 什么是存储过程? 简单的说,就是一组SQL语句集,功 ...

  4. 关于在views对models创建的表的简单操作

    models.User.objects.create(c1='a',c2='b') obj=models.User(c1='a',c2='b') obj.save() 增加 models.User.o ...

  5. 【Codeforces 1107D】Compression

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 先把所给的压缩形式的字符串转成二进制 然后对获得的01数组做一个前缀和(a[i][j]=以(i,j)为右下角,(1,1)为左上角的矩形内的数字 ...

  6. xtu read problem training 3 A - The Child and Homework

    The Child and Homework Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on Code ...

  7. Leetcode 299.猜字游戏

    猜字游戏 你正在和你的朋友玩 猜数字(Bulls and Cows)游戏:你写下一个数字让你的朋友猜.每次他猜测后,你给他一个提示,告诉他有多少位数字和确切位置都猜对了(称为"Bulls&q ...

  8. php 面向对象 (类 对象)

    //面向对象//什么是面向对象//面向过程//什么是对象?//一切皆是对象//类//由对象抽象化//造类//class Ren//{ //构造方法 - - 写不写都存在//类的初始化方法 //构造方法 ...

  9. POJ 2420 A Star not a Tree?【爬山法】

    题目大意:在二维平面上找出一个点,使它到所有给定点的距离和最小,距离定义为欧氏距离,求这个最小的距离和是多少(结果需要四舍五入)? 思路:如果不能加点,问所有点距离和的最小值那就是经典的MST,如果只 ...

  10. 飞扬的小鸟(codevs 3729)

    题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便 ...