剑指offer---以O(1)时间删除链表节点
问题:删除链表节点
要求:以O(1)时间
对于删除指定索引的链表元素大家都很熟悉,思路一般是从头遍历链表直到指定索引位置删除元素,然后维护一下指针即可,时间复杂度O(n)。代码如下:
// 删除position位置的数据,并返回
int List::erasePosition(int position){
if(position< || position>(List::size()-)){
cout<<"position error, please check."<<endl;
return -;
}
int res = List::getValue(position);
Node *p = head;
int index = ;
cout<<"erase data at position "<<position<<endl;
if(position == ){
head = p->next;
return res;
}
else{
while(index != position-){
p = p->next;
index++;
}
Node *temp = p->next;
p->next = temp->next;
return res;
}
}
上述代码的完整版在这里。
但是当删除指定地址的链表元素时,事情变得不太一样了,在这种情况下我们可以实现O(1)时间删除指定地址的数据。当然,以上是基于一个假设:要删除的节点一定在链表里面。

如上图所示,我们打算删除节点e,可以将节点e的后一个节点b的内容复制到节点e,即覆盖原有内容,然后删除后一个节点b。(这里我感觉待删除地址还是有节点的,只是内容变了,与直接删除节点e有相似的效果)
注意点:空指针与尾节点的情况(详见代码)
解题代码:
void List::erase(Node *pDelete){
if (pDelete == nullptr)
return ;
// 删除的的节点不是尾节点
if(pDelete->next != nullptr){
Node *pNext = pDelete->next;
pDelete->data = pDelete->next->data;
pDelete->next = pNext->next;
delete pNext;
pNext = nullptr;
}
// 链表只有一个节点,删除第一个节点
else if(head == pDelete){
delete pDelete;
pDelete = nullptr;
head = nullptr;
}
// 链表中有多个节点,要删除尾节点
else{
Node *p = head;
while(p->next!= pDelete){
p = p->next;
}
p->next = nullptr;
delete pDelete;
pDelete = nullptr;
}
}
完整版代码:
#include<iostream>
using namespace std; class Node {
public:
int data;
Node *next;
Node(int da):
data(da), next(NULL){}
}; class List{
public:
Node *head;
List(): head(NULL){}
~List(){
delete head;
cout<<"The list is deleted."<<endl;
};
int size();
int getValue(int position);
void printList(); // 打印链表
void insert(int position, int value); // 指定位置插入
void insertHead(int value); // 插入到最前
void insertTail(int value); // 插入到最后
int erasePosition(int position); // 删除指定位置的节点
void erase(Node *pDelete); }; // 返回position位置的数据
int List::getValue(int position){
if(position< || position>(List::size()-)){
cout<<"position error, please check."<<endl;
return -;
}
Node *p = head;
int index = ;
while(index != position){
p = p->next;
index++;
}
//cout<<"position "<<position<<" is "<<p->data<<endl;
return p->data;
} // 返回链表大小
int List::size(){
Node *p = head;
int index = ;
while(p != NULL){
index++;
p = p->next;
}
return index;
} // 打印链表
void List::printList(){
Node *p = head;
while(p != NULL){
cout<<p->data<<" ";
p = p->next;
}
cout<<endl;
cout<<endl;
} // 在position位置插入value
void List::insert(int position, int value){
if(position< || position>List::size()){
cout<<"position error, please check."<<endl;
return ;
}
Node *s = new Node(value); // new node
Node *p = head;
if(head == NULL){ // isEmpty = true
head = s;
}
else{ // isEmpty = false
if(position == ){
s->next = p;
head = s;
}
else{
int index = ;
while(index != position-){
p = p->next;
index++;
}
s->next = p->next;
p->next = s;
}
}
if (position == )
cout<<"insert "<<value<<" at the first."<<endl;
else if (position == List::size())
cout<<"insert "<<value<<" at the tail."<<endl;
else
cout<<"insert "<<value<<" at position "<<position<<endl;
} // 头部插入
void List::insertHead(int value){
List::insert(, value);
} // 尾部插入
void List::insertTail(int value){
List::insert(List::size(), value);
} // 删除position位置的数据,并返回
int List::erasePosition(int position){
if(position< || position>(List::size()-)){
cout<<"position error, please check."<<endl;
return -;
}
int res = List::getValue(position);
Node *p = head;
int index = ;
cout<<"erase data at position "<<position<<endl;
if(position == ){
head = p->next;
return res;
}
else{
while(index != position-){
p = p->next;
index++;
}
Node *temp = p->next;
p->next = temp->next;
return res;
}
} void List::erase(Node *pDelete){
cout<<"erase data at address "<<pDelete<<endl;
if (pDelete == nullptr)
return ;
// 删除的的节点不是尾节点
if(pDelete->next != nullptr){
Node *pNext = pDelete->next;
pDelete->data = pDelete->next->data;
pDelete->next = pNext->next;
delete pNext;
pNext = nullptr;
}
// 链表只有一个节点,删除第一个节点
else if(head == pDelete){
delete pDelete;
pDelete = nullptr;
head = nullptr;
}
// 链表中有多个节点,要删除尾节点
else{
Node *p = head;
while(p->next!= pDelete){
p = p->next;
}
p->next = nullptr;
delete pDelete;
pDelete = nullptr;
}
} int main() {
List l1;
l1.insertTail();
l1.insertHead();
l1.insert(, );
l1.insert(, );
l1.insert(, );
l1.insert(, );
l1.insert(, );
cout<<endl<<"The list is:"<<endl;
l1.printList();
l1.erasePosition();l1.printList();
l1.erase(l1.head);l1.printList();
return ;
}
运行结果:
insert at the first.
insert at the first.
insert at position
insert at the first.
insert at position
insert at the first.
insert at position The list is: erase data at position erase data at address 0x3b1a58 The list is deleted.
[Finished in .3s]
由于主函数传的是 l1.erase(l1.head); 所以应该是删除链表的第一个节点,可见结果正确。
剑指offer---以O(1)时间删除链表节点的更多相关文章
- 剑指offer.在O(1)时间内删除链表节点
给定单向链表的一个节点指针,定义一个函数在O(1)时间删除该结点.假设链表一定存在,并且该节点一定不是尾节点. 样例 输入:链表 1->4->6->8 删掉节点:第2个节点即6(头节 ...
- 剑指offer之 O(1)时间删除链表结点
问题描述:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. package Problem13; /* * 问题描述:给定单向链表的头指针和一个结点指针,定义一个函数在O(1 ...
- [剑指offer]Q13:O(1)时间删除链表的结点
通常我们所说的删除链表的某个结点,是彻底删除该结点的空间.而要这么做就必须知道其前驱结点.这里的想法是,链表中存储的val是同类型的,仅仅要将该结点的val内容删除就能够了. 那么就能够用该结点的后继 ...
- [刷题] 剑指offer 面试题18:删除链表节点
要求 给定单向链表的头指针和一个节点指针,在O(1)时间内删除该节点 常规思路:从头节点a开始顺序遍历,发现p指向要删除的节点i,然后把p的m_pNext指向i的下一个节点j,时间复杂度O(n) O( ...
- 【校招面试 之 剑指offer】第18题 删除链表中的节点
题目一:在O(1)时间内删除链表节点. 给定单项链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点. 思路:(1)如果要删除的节点不是链表的尾节点,则将被删除节点的内容复制到该节点,然 ...
- 剑指offer13 在O(1)时间删除链表的结点
把下一个节点的值直接赋值给要删除的节点,然后删除下一个节点.当这样做会有两个bad case:被删除的链表结点的下一个结点为空指针,如果链表只有一个结点.其实链表只有一个结点应该属于下一个结点为空指针 ...
- 剑指Offer(书):删除链表的节点
题目:在O(1)的时间内删除列表节点. /** * 步骤: * 1.检查head与removeNode节点是否为空 * 2.检查removeNode的后一个节点是否为空,不为空则使用后一个节点的值覆盖 ...
- 【剑指offer】面试题 18. 删除链表的节点
面试题 18. 删除链表的节点
- 【剑指Offer】面试题18. 删除链表的节点
题目 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点. 返回删除后的链表的头节点. 注意:此题对比原题有改动 示例 1: 输入: head = [4,5,1,9], val = 5 ...
- [剑指Offer]18-题目一:删除链表的节点 题目二:删除链表中重复节点
题目一 题目 O(1)时间复杂度删除给定链表节点. 题解 用待删除节点后一个节点的值覆盖待删除节点值,更新链接关系. 注意链表只有一个节点:删除尾结点:删除头节点的处理. 代码 class ListN ...
随机推荐
- Hadoop安装配置(ubuntu-12.04.2-server-amd64)
环境如下: ubuntu-12.04.2-server-amd64 hadoop-1.0.4 VirtualBox 1.在VBox中安装Ubuntu Server,用户名和密码都是hadoop,安装完 ...
- MAC OS brew安装MNMP
安装HomeBrew Brew是Mac下面的包管理工具,就像centos下面的yum一样.HomeBrew可以通过ruby来安装,mac系统是自带ruby的,所以只要在终端运行下面的代码即可安装Hom ...
- BZOJ_3175_[Tjoi2013]攻击装置_二分图匹配
BZOJ_3175_[Tjoi2013]攻击装置_二分图匹配Description 给定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置 ...
- 【NOI 2007】 社交网络
[题目链接] 点击打开链接 [算法] 首先,跑floyd,计算最短路和最短路径数 然后,计算答案,枚举k,s,t,若dist[s][k] + dist[k][t] = dist[s][t], 那么,点 ...
- python-----查看显卡gpu信息
需要安装pynvml库. 下载地址为:https://pypi.org/project/nvidia-ml-py/#history pip安装的命令为: pip install nvidia-ml-p ...
- Tomcat + solr5.2.1环境搭建
1. 下载solr并解压后的目录为:E:\solr-5.2.1 , http://lucene.apache.org/solr/downloads.html 2. 将solr部署到Tomcat中 ...
- jquery plupload上传插件
http://www.jianshu.com/p/047349275cd4 http://www.cnblogs.com/2050/p/3913184.html demo地址: http://chap ...
- bzoj 1679: [Usaco2005 Jan]Moo Volume 牛的呼声【枚举】
直接枚举两两牛之间的距离即可 #include<iostream> #include<cstdio> #include<algorithm> using names ...
- Linux day01(二)虚拟机快照和克隆的用法介绍
一:快照 优点:运行虚拟机后不用担心系统会被弄崩溃了,点击快照会立即恢复到初始状态 缺点:回滚会带来数据的丢失,所以要考虑数据恢复的成本和找回数据时进行操作的成本 1. 在导航栏中找虚拟机快照的小图标 ...
- CentOS 7 配置 Nginx 正向代理 http、https 最详解
手头项目中有使用到 nginx,因为使用的三方云服务器,想上外网需要购买外网IP的,可是有些需要用到外网却不常用的主机也挂个外网IP有点浪费了,便想使用nginx的反向代理来实现多台内网服务器使用一台 ...