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

自己所写代码如下:

//以O(1)时间删除链表节点
//要求:单向链表,头指针,待删节点指针 //链表节点
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
};
//O(n)的解法:从头遍历,找到pToBeDeleted所指节点的前一个节点再进行删除
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
if(pListHead == NULL || *pListHead == NULL || pToBeDeleted == NULL)
return; ListNode* pNode = *pListHead;
if(pNode == pToBeDeleted) //对pToBeDeleted指向头结点情况的处理
{
*pListHead = (*pListHead)->m_pNext;
delete pToBeDeleted;
pToBeDeleted = NULL;
}
else
{
while(pNode->m_pNext != NULL && pNode->m_pNext != pToBeDeleted)
pNode = pNode->m_pNext ; if(pNode->m_pNext == NULL)
{
cout<<"pToBeDeleted不在链表中!"<<endl;
return;
} pNode->m_pNext = pToBeDeleted->m_pNext;
delete pToBeDeleted;
pToBeDeleted = NULL; } } //O(1)的解法:复制后一个节点以覆盖待删节点,再删除重复的后一个节点
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
if(pListHead == NULL || *pListHead == NULL || pToBeDeleted == NULL)
return; ListNode* pNode = *pListHead;
if(pNode == pToBeDeleted)
{
*pListHead = (*pListHead)->m_pNext;
delete pToBeDeleted;
pToBeDeleted = NULL;
}
else
{
pNode = pToBeDeleted->m_pNext;
//排除pToBeDeleted指向尾节点的情形
if(pNode == NULL)
{
pNode = *pListHead;
while(pNode->m_pNext != pToBeDeleted)
pNode = pNode->m_pNext ; pNode->m_pNext = NULL; delete pToBeDeleted;
pToBeDeleted = NULL;
}
else
{
pToBeDeleted->m_nValue = pNode->m_nValue;
pToBeDeleted->m_pNext = pNode->m_pNext;
delete pNode;
pNode = NULL;
} }
}

在以上O(1)的代码中,自己的想法有些呆板,具体来说:采用复制覆盖的方法则应考虑的是pToBeDeleted指向尾节点的特殊情况(此时,无法复制!)

而非pToBeDeleted指向头结点的情况(这是O(n)的特殊情况!)!!!

O(n)的方法:需要找前驱节点,所以考虑头结点的特殊情况;

O(1)的方法:需要找后继节点,所以考虑尾节点的特殊情况。

代码修改如下:

//O(1)的解法:复制后一个节点以覆盖待删节点,再删除重复的后一个节点
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
if(pListHead == NULL || *pListHead == NULL || pToBeDeleted == NULL)
return; ListNode* pNode = pToBeDeleted->m_pNext;
//排除pToBeDeleted指向尾节点的情形
if(pNode == NULL)
{
pNode = *pListHead;
if(pNode == pToBeDeleted)
{
delete pToBeDeleted;
*pListHead = pToBeDeleted = NULL;
}
else
{
while(pNode->m_pNext != pToBeDeleted)
pNode = pNode->m_pNext; pNode->m_pNext = NULL; delete pToBeDeleted;
pToBeDeleted = NULL;
} }
else
{
pToBeDeleted->m_nValue = pNode->m_nValue;
pToBeDeleted->m_pNext = pNode->m_pNext;
delete pNode;
pNode = NULL;
} }

和参考代码相一致!赞一个!

总结:1、突破常规思维,删除节点不一定需要从头遍历链表,可以用下一结点复制并覆盖待删节点,最后再删除重复的下一结点。

   2、考虑问题全面性:若待删节点为尾节点,则下一个节点为空;若整个链表仅一个节点,删除后,头结点同时设为NULL。

      这些都需要特殊对待!!!

剑指offer--面试题13的更多相关文章

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

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

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

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

  3. 剑指Offer——笔试题+知识点总结

    剑指Offer--笔试题+知识点总结 情景回顾 时间:2016.9.23 12:00-14:00 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:笔试 注意事项:要有大局观, ...

  4. C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告

    剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...

  5. C++版 - 剑指offer 面试题23:从上往下打印二叉树(二叉树的层次遍历BFS) 题解

    剑指offer  面试题23:从上往下打印二叉树 参与人数:4853  时间限制:1秒  空间限制:32768K 提交网址: http://www.nowcoder.com/practice/7fe2 ...

  6. C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解

    剑指offer 面试题39:判断平衡二叉树 提交网址:  http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...

  7. Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)

    剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...

  8. C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解

    剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...

  9. C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解

    剑指offer 面试题24:二叉搜索树的后序遍历序列(的判断) 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true.否则返回false.假设输入的数组的任意两个 ...

  10. C++版 - 剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题,ZOJ 1088:System Overload类似)题解

    剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题) 原书题目:0, 1, - , n-1 这n个数字排成一个圈圈,从数字0开始每次从圆圏里删除第m个数字.求出这个圈圈里剩下的最后一个数字 ...

随机推荐

  1. Java中的哈希

    Java中的哈希 前言 在开发中经常用到HashMap.HashSet等与哈希有关的数据结构,一直只知道这些哈希的数据结构不保证顺序,不清楚具体什么情况.所以在这里大致总结一下.   Java的Has ...

  2. 1 。 LightOJ 1234 打表法(数据太大,把数据缩小100倍)

    原题链接http://acm.hust.edu.cn/vjudge/contest/121397#problem/A Description In mathematics, the nth harmo ...

  3. unity 3消 游戏

    3消游戏跟着智能手机流行到现在已经有很长一段时间,unity实现的3消 https://github.com/textcube/match3action 截图如下: 在阅读源码的时候不难发现,Game ...

  4. [windows phone开发]新生助手的开发过程与体会二

    上一讲咱们谈了新生助手主页的基本的设计,今天我们谈一谈关于展现实景地图时等动画的设计,即Storyboard的应用. 在Windows phone中,Storyboard类表示通过时间线控制动画,并为 ...

  5. 【风马一族_Android】Android 前端内容1

    Android 前端内容 4.1 View 类概述 4.1.1 关于 View //类型说明 view(视图)指的是用户界面组件的基本构建基块.一个视图占据屏幕上的矩形区域,负责绘图和事件处理.视图是 ...

  6. ROS ZYNQ移植

    1  准备工作 全部是按照官方操作的:http://wiki.ros.org/groovy/Installation/Source   apt-get install python-rosdep py ...

  7. ADO.NET笔记——使用DataSet返回数据

    相关知识: DataSet和DataAdapter的内部结构: DataSet通过DataAdapter从数据库中获取数据 DataSet对象内部包括一个集合(Tables),也就是可以拥有多个表(D ...

  8. 支持IE6的树形节结构TreeTable实际应用案例

    <script src="jquery.js" type="text/javascript"></script> <script ...

  9. AngularJS(13)-包含

    AngularJS 包含 使用 AngularJS, 你可以使用 ng-include 指令来包含 HTML 内容: 实例 <body> <div class="conta ...

  10. php学习日志(5)-解决Windows Live Writer错误:WindowsLive.Writer.CoreServices.HttpRequestHelper的类型初始值设定发生异常

    以前用Windows Live Writer写日志都好好的,前几天用写完日志,点击发布,突然弹出意外错误:“WindowsLive.Writer.CoreServices.HttpRequestHel ...