题目:以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. 如何防止Android应用代码被窃

    上一篇我们讲了apk防止反编译技术中的加壳技术,如果有不明白的可以查看我的上一篇博客http://my.oschina.net/u/2323218/blog/393372.接下来我们将介绍另一种防止a ...

  2. 下拉框的选择跳转事件(jqure)

    <select id="coupontype"> <option value="@CouponType.全部" href="@Url ...

  3. (转)Yale CAS + .net Client 实现 SSO(6)

    第一部分:安装配置 Tomcat 第二部分:安装配置 CAS 第三部分:实现 ASP.NET WebForm Client 第四部分:实现基于数据库的身份验证 第五部分:扩展基于数据库的身份验证 第六 ...

  4. String中重要方法与字段

    下列这段代码已全部包含了我要写的String类中重要的字段: //StringMisc.java// This program demonstrates the length, charAt and ...

  5. format——MATLAB

    format:设置输出格式 对浮点性变量,缺省为format short. format并不影响matlab如何计算和存储变量的值.对浮点型变量的计算,即单精度或双精度,按合适的浮点精度进行,而不论变 ...

  6. 已有数据表的Mysql字符编码修改

    Mysql字符集修改应该如何实现呢?下面就为您详细介绍已用数据表的Mysql字符集修改方法,希望对您学习Mysql字符集方面能有所启迪. 环境:在应用开始阶段没有正确的设置字符集,在运行一段时间以后才 ...

  7. js动态引入的四种方式

    index.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http:// ...

  8. ADO.NET笔记——基本概念

    ADO.NET中的主要对象: Connection:连接对象.用于建立从应用程序到数据库服务器指定数据库的连接通道 Command:命令对象.用于执行增删查改等数据库语句命令 DataReader:数 ...

  9. ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK

    看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, 加入一个表10W数据,另一个表也是10万数据,当你用linq建立一个连接查询 ...

  10. 另辟思路解决 Android 4.0.4 不能监听Home键的问题

    问题描述: 自从Android 4.0以后,开发人员是不能监听和屏蔽Home键的,对于KEYCODE_HOME,官方给出的描述如下: Home key. This key is handled by ...