题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点。

链表节点与函数的定义如下。

通常我们删除某个节点都是从头开始遍历到需要删除节点的前一个节点。

然后使得该节点的next指向删除节点的next即可,这样看来删除一个节点

的复杂度为O(n)然而我们其实遍历的目的只是想获取想要删除节点的前一

个节点。

那么我们可以这样考虑:

我们把要删除节点下一个节点的值赋值到当前节点,然后将当前节点的下一个

节点删除即可。

比如:

一个链表3->2->5->7->9给定的指针指向5也就是说要删除5这个节点。

我们将节点5下个节点的值赋值给需要删除的节点即:

3->2->7->7->9

然后再p->next=p->next->next即可删除

代码实现如下:

 /**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
void deleteNode(struct ListNode* node)
{
if(node==NULL)
return; struct ListNode* p,*q;
q=node;
p=node->next;
q->val=p->val;
q->next=p->next; }

勘误:

上面的方法没有考虑到当要删除的结点是尾结点的情况

因此当需要删除的结点为尾结点的时候这时候仍需要

从头遍历到尾结点的前面一个结点。

但是算法复杂度仍然为1,因为只有一个尾结点需要遍历

整个链表,复杂度为(O(n)+O(1)*(n-1))/n=O(1)

代码实现如下:

 #include <iostream>
using namespace std; /**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode
{
int val;
struct ListNode *next;
}; ListNode *head; void deleteNode(struct ListNode* node)
{
if(node==NULL)
return;
if(node->next==NULL)
{
ListNode *TempHead;
TempHead=head;
while(TempHead->next->next!=NULL)
{
TempHead=TempHead->next;
}
TempHead->next=NULL;
return;
} struct ListNode *p,*q;
q=node;
p=node->next;
q->val=p->val;
q->next=p->next;
} ListNode* CreateList()
{
ListNode *Head,*p;
Head=(ListNode*)malloc(sizeof(ListNode));
if(Head==NULL)
return NULL; Head->val=;
Head->next=NULL;
p=Head;
while(true)
{
int data;
cout<<"Please input Node data: ";
cin>>data;
if(data==)
{
break;
}
else
{
ListNode* NewNode;
NewNode=(ListNode*)malloc(sizeof(ListNode));
NewNode->val=data;
NewNode->next=NULL;
p->next=NewNode;
p=p->next;
}
} return Head->next;
} void PrintList(ListNode* Head)
{
ListNode *p;
p=Head; while(p!=NULL)
{
cout<<p->val<<",";
p=p->next;
}
} ListNode* GetNodePtr(ListNode* Head)
{
int count;
ListNode* p;
p=Head;
cout<<"Please input the Node Order you want to delete: ";
cin>>count;
int i=;
while(i<count-)
{
p=p->next;
i++;
} return p;
} int main()
{
ListNode *Node;
head=CreateList();
cout<<"The list is: ";
PrintList(head);
cout<<endl;
Node=GetNodePtr(head);
deleteNode(Node);
cout<<"The delete node list is: ";
PrintList(head);
cout<<endl;
return ;
}

测试结果如下:

感谢@rainhard指出这个错误

剑指offer-面试题13.在O(1)时间删除链表节点的更多相关文章

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

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

  2. 《剑指offer》面试题13 在O(1)时间删除链表节点 Java版

    这道题的关键是知道找到尾节点的前一个节点必须遍历,而且这样做了之后总的时间复杂度还是O(1),以及如何不破坏链表删除一个已知节点 public ListNode delete(ListNode hea ...

  3. 面试题13:在O(1)时间删除链表节点

    http://blog.csdn.net/jsqfengbao/article/details/47175249

  4. 剑指offer编程题Java实现——面试题13在O(1)时间内删除链表节点

    题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点. 由于给定的是单向链表,正常删除链表的时间复杂度是查找链表的时间复杂度即O(n),如果要求在O(1)时间复杂度内删除节点 ...

  5. 【剑指Offer面试题】 九度OJ1518:反转链表

    与其非常快写出一段漏洞百出的代码,倒不如细致分析再写出鲁棒的代码. 提前想好測试用例(输入非空等等)进行測试改动代码. 题目链接地址: http://ac.jobdu.com/problem.php? ...

  6. 题目13 在O(1)时间删除链表节点

    ///////////////////////////////////////////////////////////////////////////////////// // 3. 题目13 在O( ...

  7. C++版 - 剑指offer 面试题5:从尾到头打印链表 题解

    面试题5:从尾到头打印链表 提交网址: http://www.nowcoder.com/practice/d0267f7f55b3412ba93bd35cfa8e8035?tpId=13&tq ...

  8. 【剑指offer 面试题13】在 O(1) 时间删除链表结点

    #include <iostream> using namespace std; //构造链表结点 struct ListNode { int val; ListNode *next; L ...

  9. 剑指Offer面试题15(Java版):链表中倒数第K个结点

    题目: 输入一个链表.输出该链表中倒数第k哥结点.  为了符合大多数人的习惯,本题从1開始计数.即链表的尾结点是倒数第1个结点. 比如一个链表有6个结点.从头结点開始它们的值依次是1.2.3,4,5, ...

随机推荐

  1. Linux 程序设计的一些优化措施

    Linux 程序设计的一些优化措施 这些知识是在平常的阅读中,零散的获得的,自己总结了一下,分享在这里 全局变量VS函数参数 全局变量在Linux下的驱动编程里边,用的是非常多,例如中断服务函数ISR ...

  2. functools:管理函数工具(部分)

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #functools:管理函数工具 #作用:处理其他函数的函数 #版 ...

  3. springmvc工作原理和环境搭建

    SpringMVC工作原理     上面的是springMVC的工作原理图: 1.客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServle ...

  4. InnoDB和MyISAM存储引擎的区别

    在MySQL数据库的使用过程中我们经常会听到存储引擎这个名词.MySQL的存储引擎有好多种如InnoDB.MyISAM.Memory.NDB等等,多存储引擎也是MySQL数据库的特色. InnoDB和 ...

  5. Oracle 事务的開始与结束

    事务是用来切割数据库活动的逻辑工作单元,事务即有起点,也有终点: 当下列事件之中的一个发生时,事务就開始了: 连接到数据库上,并运行了第一天 DML 语句: 当前一个事务结束后,又输入了另外一条 DM ...

  6. [跟我学spring学习笔记][DI循环依赖]

    循环依赖 什么是循环依赖? 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方. Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢? ...

  7. react-native使用react-art制作SVG动画

    想要使用SVG做一个动画,郁闷了一上午终于有了一点思路.. 其实我是看了一篇国外的文章.网址:http://browniefed.com/blog/2015/05/03/getting-react-a ...

  8. ibatis复用SQL片段、引入片段 动态条件增加

    1:ibatis复用SQL片段.引入片段  使用[sql]和[include]标签: 通常情况下,你会这样写:xml 代码 <select id="selectItemCount&qu ...

  9. javascript父窗口与子窗口通信

    在父窗口的js代码 //回调的函数 function alt(temp){ alert(temp); }; $("#Btn").click(function (obj) { //声 ...

  10. 虚拟机VirtualBox和Ubutu

    虚拟机的作用1. 演示环境,可以安装各种演示环境,便于做各种例子: 2. 保证主机的快速运行,减少不必要的垃圾安装程序,偶尔使用的程序,或者测试用的程序在虚拟机上运行: 3. 避免每次重新安装,银行等 ...