题目:以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. .NET打印功能实现 PrintDocument

    //打印按钮 private void btnPrint_Click(object sender, EventArgs e) { if (this.printDialog1.ShowDialog() ...

  2. 网络请求的null值处理

    最近项目中经常有遇到从服务器请求的数据是null的情况,这种情况下如果用[dic objectForKey:@"key"]方法,程序会发生崩溃现象,因为项目是以前的老项目,而且有太 ...

  3. java使用BufferedImage和Graphics实现图片合成

    package com.igoxin.weixin.custom; import java.awt.Graphics; import java.awt.image.BufferedImage; imp ...

  4. java中对集合对象list的几种循环访问

    java中对集合对象list的几种循环访问的总结如下 1 经典的for循环 public static void main(String[] args) { List<String> li ...

  5. 初测WIN10

    WIN10已经发布,通过百度直通车把WIN7升级成了WIN10,改变较大,不太习惯,用着不是很顺手. 吐槽几个问题 1.微软的Visual Studio 2015 Community版本,宣布是免费的 ...

  6. margin的BUG

    在进行简单的div盒子嵌套时,发现设置margin-top时存在bug,然后就去谷歌搜索了一下,发现margin确实存在bug. bug的现象是父子元素嵌套时,如果子元素是块元素时,对块元素设置mar ...

  7. itertools模块速查

    学习itertools模块记住这张表就OK了 参考:http://docs.python.org/2/library/itertools.html#module-itertools Infinite ...

  8. 【Web学习日记】——C#引用WebService,从配置文件改变引用地址

    开发环境:Win7 32位,开发工具:VS2013,.Net:4.0 初用WebService,很多地方都搞不清楚怎么回事,但稍作研究之后,也就用上了,根本就没有考虑后续事情. 但是,随着项目的进行, ...

  9. GITHUB 提交错误 Error: Permission denied (publickey) 解决

    1.  在开发机上生成自己的密钥 ssh-keygen -b 1024 -t rsa -b 指密钥对长度  -t 指加密方式 Enter file in which to save the key ( ...

  10. JMS之开源实现ActiveMQ

    1.ActiveMQ是开源的JMS实现. 可以把不影响用户执行结果又比较耗时的任务(比如发邮件通知管理员)异步的扔给jms 服务端,而尽快的把屏幕返还给用户,且服务端能够多线程排队响应高并发的请求.可 ...