lintCode(372)——在O(1)时间复杂度删除链表节点
2016-04-08 10:10
246 查看
题目描述:
给定一个单链表中的表头和一个等待被删除的节点。请在在O(1)时间复杂度删除该链表节点。并在删除该节点后,返回表头。
样例:给定 1->2->3->4,和节点 3,返回 1->2->4。
这是一道广为流传的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)。
基于前面的分析,我们不难写出下面的代码。
给定一个单链表中的表头和一个等待被删除的节点。请在在O(1)时间复杂度删除该链表节点。并在删除该节点后,返回表头。
样例:给定 1->2->3->4,和节点 3,返回 1->2->4。
这是一道广为流传的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)。
基于前面的分析,我们不难写出下面的代码。
/** * Definition of ListNode * class ListNode { * public: * int val; * ListNode *next; * ListNode(int val) { * this->val = val; * this->next = NULL; * } * } */ class Solution { public: /** * @param node: a node in the list should be deleted * @return: nothing */ void deleteNode(ListNode** pHead,ListNode *node) { // write your code here if(pHead==NULL||node==NULL) return; //要删除的结点不是尾结点 if(node->next!=NULL){ ListNode* pNext=node->next; node->val=pNext->val; node->next=pNext->next; delete pNext; pNext=NULL; } //链表只有一个结点,删除头结点(也是尾结点) else if(*pHead==node) { delete node; node=NULL; *pHead=NULL; } //要删除的结点是尾结点,且链表有多个结点 else { ListNode* pNode=*pHead; while(pNode->next!=node) { pNode=pNode->next; } pNode->next=NULL; delete node; node=NULL; } }
相关文章推荐
- 简单的遮罩
- adb不是内部命令 --windows系统
- JS在页面Frame和子Frame之间的调用
- 给 Linux 系统“减肥”,系统垃圾清理
- [置顶] php编写冒泡排序
- 我是如何自学Android,资料分享
- 定义回调函数的方法
- 去掉UItableview headerview黏性
- Linux groupmod --修改用户组
- Linux groupdel --删除群组
- 算法_动态规划_漂亮打印
- C++第二次实验作业
- Android全屏(包含3种隐藏顶部状态栏及标题栏和一种隐藏Android 4.0平板底部状态栏的方法)
- 一个Demo让你掌握Android所有控件
- Oracle非重要文件恢复,redo、暂时文件、索引文件、password文件
- jquery 一些简单代码
- java注解
- MySQL ・ 引擎特性 ・ InnoDB 文件系统之文件物理结构
- 解决listView的item无法响应点击事件onItemClickListener的问题
- CentOS 6使用rpm方式安装JDK8