剑指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 ...
随机推荐
- sa分析
onCheckedChanged用于监控开启和关闭,其实是Switch,也是Toggle Buttons http://www.google.com/design/spec/components/sw ...
- virtual (C# Reference)
https://msdn.microsoft.com/en-us/library/9fkccyh4.aspx The virtual keyword is used to modify a metho ...
- hdoj--1877--又一版 A+B(水题)
又一版 A+B Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- luogu 3958 奶酪
noip2017 D2T1 奶酪 某zz选手没有想到可以用并查集来做,直接用了dijskstra,结果被ccf老爷机卡成了70分 题目大意: 现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为 ...
- bzoj1597 [Usaco2008 Mar]土地购买——斜率优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1597 就是斜率优化水题... 然而WA了十几遍,正负号处理真让人心累... 还是该负就负,别 ...
- 公司4:JrVue主题定制
JrVue是我们基于element重新封装的一套组件库; 具体组件使用方法可以mnote->研发小组查看; 这里我们定制了一套主题色, 具体变动如下: 1.主题色变动: mfront有蓝.紫. ...
- 贪心/思维题 UVA 11292 The Dragon of Loowater
题目传送门 /* 题意:n个头,m个士兵,问能否砍掉n个头 贪心/思维题:两个数组升序排序,用最弱的士兵砍掉当前的头 */ #include <cstdio> #include <c ...
- Generating RSA keys in PKCS#1 format in Java--转
原文地址:https://stackoverflow.com/questions/7611383/generating-rsa-keys-in-pkcs1-format-in-java When I ...
- js易混API汇总
一:slice()方法 ————————————http://www.w3school.com.cn/jsref/jsref_slice_string.asp ———————————————————— ...
- jQuery学习笔记(4)-设置元素的属性和样式
一.前言 本篇主要讲解如何使用jQuery获取和操作元素的属性和css样式 二."DOM属性"与元素属性 1.运行一下代码 <img src="/images/lo ...