问题:删除链表节点

要求:以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)时间删除链表节点的更多相关文章

  1. 剑指offer.在O(1)时间内删除链表节点

    给定单向链表的一个节点指针,定义一个函数在O(1)时间删除该结点.假设链表一定存在,并且该节点一定不是尾节点. 样例 输入:链表 1->4->6->8 删掉节点:第2个节点即6(头节 ...

  2. 剑指offer之 O(1)时间删除链表结点

    问题描述:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. package Problem13; /* * 问题描述:给定单向链表的头指针和一个结点指针,定义一个函数在O(1 ...

  3. [剑指offer]Q13:O(1)时间删除链表的结点

    通常我们所说的删除链表的某个结点,是彻底删除该结点的空间.而要这么做就必须知道其前驱结点.这里的想法是,链表中存储的val是同类型的,仅仅要将该结点的val内容删除就能够了. 那么就能够用该结点的后继 ...

  4. [刷题] 剑指offer 面试题18:删除链表节点

    要求 给定单向链表的头指针和一个节点指针,在O(1)时间内删除该节点 常规思路:从头节点a开始顺序遍历,发现p指向要删除的节点i,然后把p的m_pNext指向i的下一个节点j,时间复杂度O(n) O( ...

  5. 【校招面试 之 剑指offer】第18题 删除链表中的节点

    题目一:在O(1)时间内删除链表节点. 给定单项链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点. 思路:(1)如果要删除的节点不是链表的尾节点,则将被删除节点的内容复制到该节点,然 ...

  6. 剑指offer13 在O(1)时间删除链表的结点

    把下一个节点的值直接赋值给要删除的节点,然后删除下一个节点.当这样做会有两个bad case:被删除的链表结点的下一个结点为空指针,如果链表只有一个结点.其实链表只有一个结点应该属于下一个结点为空指针 ...

  7. 剑指Offer(书):删除链表的节点

    题目:在O(1)的时间内删除列表节点. /** * 步骤: * 1.检查head与removeNode节点是否为空 * 2.检查removeNode的后一个节点是否为空,不为空则使用后一个节点的值覆盖 ...

  8. 【剑指offer】面试题 18. 删除链表的节点

    面试题 18. 删除链表的节点

  9. 【剑指Offer】面试题18. 删除链表的节点

    题目 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点. 返回删除后的链表的头节点. 注意:此题对比原题有改动 示例 1: 输入: head = [4,5,1,9], val = 5 ...

  10. [剑指Offer]18-题目一:删除链表的节点 题目二:删除链表中重复节点

    题目一 题目 O(1)时间复杂度删除给定链表节点. 题解 用待删除节点后一个节点的值覆盖待删除节点值,更新链接关系. 注意链表只有一个节点:删除尾结点:删除头节点的处理. 代码 class ListN ...

随机推荐

  1. sa分析

    onCheckedChanged用于监控开启和关闭,其实是Switch,也是Toggle Buttons http://www.google.com/design/spec/components/sw ...

  2. virtual (C# Reference)

    https://msdn.microsoft.com/en-us/library/9fkccyh4.aspx The virtual keyword is used to modify a metho ...

  3. hdoj--1877--又一版 A+B(水题)

     又一版 A+B Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  4. luogu 3958 奶酪

    noip2017 D2T1 奶酪 某zz选手没有想到可以用并查集来做,直接用了dijskstra,结果被ccf老爷机卡成了70分 题目大意: 现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为 ...

  5. bzoj1597 [Usaco2008 Mar]土地购买——斜率优化DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1597 就是斜率优化水题... 然而WA了十几遍,正负号处理真让人心累... 还是该负就负,别 ...

  6. 公司4:JrVue主题定制

    JrVue是我们基于element重新封装的一套组件库;  具体组件使用方法可以mnote->研发小组查看; 这里我们定制了一套主题色, 具体变动如下: 1.主题色变动: mfront有蓝.紫. ...

  7. 贪心/思维题 UVA 11292 The Dragon of Loowater

    题目传送门 /* 题意:n个头,m个士兵,问能否砍掉n个头 贪心/思维题:两个数组升序排序,用最弱的士兵砍掉当前的头 */ #include <cstdio> #include <c ...

  8. Generating RSA keys in PKCS#1 format in Java--转

    原文地址:https://stackoverflow.com/questions/7611383/generating-rsa-keys-in-pkcs1-format-in-java When I ...

  9. js易混API汇总

    一:slice()方法 ————————————http://www.w3school.com.cn/jsref/jsref_slice_string.asp ———————————————————— ...

  10. jQuery学习笔记(4)-设置元素的属性和样式

    一.前言 本篇主要讲解如何使用jQuery获取和操作元素的属性和css样式 二."DOM属性"与元素属性 1.运行一下代码 <img src="/images/lo ...