第18题:在O(1)时间删除链表结点+删除链表中重复的节点
题目描述:题目描述在O(1)时间删除链表结点
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。
考查创新编程能力。
思路:
1.如果从头到尾遍历,时间O(n)
2.如果将待删除节点的下一个节点j复制到待删除节点i上,然后将i的下一个节点指向j的下一个节点,删除j的节点。
3.对于尾节点,需要从头开始遍历
4.对于只有一个节点的链表,要将*HeadNode设置为Nullptr.
5.时间复杂度
n-1个非尾节点,时间O(1)
1个尾节点,时间O(n)
最终((n-1)*O(1)+O(n))/n=O(1)符合题目要求
注意:
1.每次删除完节点后,要释放节点,即将节点的指针设为nullptr。
2.n-1个非尾节点,删除的是待删除节点的下一个pNext,而不是本身的节点。
3.最后一个尾节点,用while遍历,pNode指针向后指,找到最后一个节点,删除后,将pNode->Next设为nullptr。
//已知该节点存在链表中
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
//1.如果链表头节点或待删除节点为空,返回
if (!pListHead || !pToBeDeleted)
return;
//2.多个节点的链表,前n-1个非尾节点
if (pToBeDeleted->m_pNext)
{
//2.1 pNext:待删除节点J的下个节点K
ListNode* pNext = pToBeDeleted->m_pNext;
//2.2 复制值J=K
pToBeDeleted->m_nValue = pNext->m_nValue;
//2.3 复制指针J->NEXT=K->NEXT
pToBeDeleted->m_pNext = pNext->m_pNext;
//2.4 删去下个节点K(pNext)
delete pNext;
//2.5 pNext设为空指针
pNext = nullptr;
}
//3.只有一个节点的链表,删完要将头节点指针设为空
else if(*pListHead==pToBeDeleted)
{
//3.1删除节点
delete pToBeDeleted;
//3.2 释放删除节点的指针
pToBeDeleted = nullptr;
//3.3 删除后将头节点设为空指针
*pListHead = nullptr;
}
//4.如果是最后一个尾节点,就用遍历
else
{
//4.1 pNode:遍历指针,从头开始
ListNode* pNode = *pListHead;
//4.2 while遍历找到pNode的下一个节点是要删除的节点
while(pNode->m_pNext == pToBeDeleted)
{
//4.2.1 指针向后指
pNode = pNode->m_pNext;
}
//4.3 将pNode的下一个节点设为空
pNode->m_pNext = nullptr;
//4.4 删除最后的节点
delete pToBeDeleted;
//4.5 释放指针
pToBeDeleted = nullptr;
}
}
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
思路:
1.确定函数的参数,头节点也可能被删除,所以函数声明应该为
void deleteDuplication(ListNode** pHead);
2.从头到尾遍历链表,确保pPreNode始终和下一个没有重复的节点连在一起。
//函数的参数:ListNode** pHead。
//因为头节点可能重复,会被删除,所以不用ListNode* pHead
void DeleteDuplication(ListNode** pHead)
{
//1.如果是空链表或头节点为空,返回
if (!pHead || !*pHead)
return;
//2.ListNode* pNode:初始化指向当前头节点*pHead
ListNode* pNode = *pHead;
//3.ListNode* pPreNode:指向上个节点,初始化为空
ListNode* pPreNode = nullptr;
//4.循环遍历
while (pNode)
{
//4.1.新建一个节点pNext,指向下个节点
ListNode* pNext = pNode->m_pNext;
//4.2 设置标记:pNode节点是否需要删除
bool needDetele = false;
//4.3 如果下个节点pNext不为空,且pNode节点值和下个节点pNext的值相同,pNode节点就需要删除
if (pNext!=nullptr && pNext->m_nValue == pNode->m_nValue)
needDetele = true;
//4.4 如果不需要删除,就遍历下一个
if (!needDetele)
{
//4.4.1 上个节点pPreNode设为当前节点pNode
pPreNode = pNode;
//4.4.2 当前节点pNode设为下个节点pNext
pNode = pNext;
/* pNode->m_nValue = pNext->m_nValue;
pNode->m_pNext = pNext->m_pNext;*/
}
//4.5 否则,开始删除
else
{
//4.5.1 记录pNode值
int value = pNode->m_nValue;
//4.5.2 定义要删除的节点变量toBeDeleted,初始化为该节点
ListNode* toBeDeleted = pNode;
//4.5.3 循环遍历:如果toBeDeleted节点不为空,且等于下一个节点,就将toBeDeleted删除,
while (toBeDeleted&&value == toBeDeleted->m_nValue)
{
//4.5.3.1 pNext指向toBeDeleted下个节点
pNext = toBeDeleted->m_pNext;
//4.5.3.2 删除toBeDeleted节点
delete toBeDeleted;
toBeDeleted = nullptr;
//4.5.3.3 toBeDeleted节点赋值为下个节点pNext
toBeDeleted = pNext;
}
//4.5.4 如果删除的是头节点,即pPreNode为空,将头节点改为下个节点
if (!pPreNode)
*pHead = pNext;
//4.5.5 否则,将pPreNode的下个节点设置为下个节点pNext
else
pPreNode->m_pNext = pNext;
//4.5.6 当前节点pNode设为下个节点pNext
pNode = pNext;
}
}
}
第二遍
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
//1.如果链表为空或者头节点为空,返回nullptr
if(!pHead)
return nullptr;
//2.pPreNode指向上一个节点,初始化为nullptr;
ListNode* pPreNode = nullptr;
//3.当前节点pNode,初始化指向头节点
ListNode* pNode=pHead;
//4.删除重复节点,while循环条件:pNode不为空
while(pNode)
{
//4.1 pNext指向pNode下个节点
ListNode* pNext= pNode->next;
//4.2 bool标记pNode是否需要删除,默认值false
bool needDelete=false;
//4.3 更新needDelete标记值:如果pNode的值和下个节点pNext的值相等的话,这个节点需要删除
if(pNext&&pNode->val==pNext->val)
needDelete=true;
//4.4 如果不需要删除,当前节点pNode向后指一个pNext,上一个节点pPreNode指向当前节点
if(!needDelete)
{
pPreNode=pNode;
pNode=pNext;
}
//4.5 否则需要删除
else
{
//4.5.1 存放当前pNode的值int
int value=pNode->val;
//4.5.2 定义待删除的节点toBeDeleted
ListNode* toBeDeleted=pNode;
//4.5.2 如果待删除的节点toBeDeleted存在,且值等于当前pNode的值,则删除该节点
while(toBeDeleted&&toBeDeleted->val==value)
{
//4.5.2.1 保存待删除节点的下个节点
pNext=toBeDeleted->next;
//4.5.2.2 删除该节点
delete toBeDeleted;
toBeDeleted=nullptr;
//4.5.2.3 重新更新待删除的节点
toBeDeleted=pNext;
}
//4.5.3 如果上个节点为空,即头节点被删除,头节点为pNext
if(!pPreNode)
pHead=pNext;
//4.5.4上一个节点pPreNode指向当前节点
else
pPreNode->next=pNext;
//4.6 将当前节点pNode向后指一个pNext
pNode=pNext;
}
}
//5. 返回链表
return pHead;
}
};
网友的
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if (pHead==NULL)
return NULL;
if (pHead!=NULL && pHead->next==NULL)
return pHead;
ListNode* current;
if ( pHead->next->val==pHead->val){
current=pHead->next->next;
while (current != NULL && current->val==pHead->val)
current=current->next;
return deleteDuplication(current);
}
else {
current=pHead->next;
pHead->next=deleteDuplication(current);
return pHead;
}
}
};
第18题:在O(1)时间删除链表结点+删除链表中重复的节点的更多相关文章
- 【IT笔试面试题整理】删除无序链表中重复的节点
[试题描述]定义一个函数,输入一个链表,删除无序链表中重复的节点 [参考代码] 方法一: Without a buffer, we can iterate with two pointers: &qu ...
- 【剑指offer】删除链表中重复的节点,C++实现(链表)
0.简介 本文是牛客网<剑指offer>笔记. 1.题目 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针.例如,链表1-> ...
- php实现删除链表中重复的节点
php实现删除链表中重复的节点 一.总结 二.php实现删除链表中重复的节点 题目描述: 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1 ...
- 剑指offer——面试题18.1:删除链表中重复的节点
// 面试题18(二):删除链表中重复的结点 // 题目:在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复 // 结点被删除之后,链表如图3.4(b)所示. #include &l ...
- 【Offer】[18-2] 【删除链表中重复的节点】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3- ...
- AcWing 29. 删除链表中重复的节点
题目地址 https://www.acwing.com/problem/content/description/27/ 来源:剑指Offer 题目描述在一个排序的链表中,存在重复的结点,请删除该链表中 ...
- 剑指offer(56)删除链表中重复的节点
一直忘记更新了,把剑指offer更新完吧.... 题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3-&g ...
- pta 奇数值结点链表&&单链表结点删除
本题要求实现两个函数,分别将读入的数据存储为单链表.将链表中奇数值的结点重新组成一个新的链表.链表结点定义如下: struct ListNode { int data; ListNode *next; ...
- python实现剑指offer删除链表中重复的节点
题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...
随机推荐
- bzoj1004 [HNOI2008]Cards【Burnside/Polya】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1004 一道好题,但并不是好在融合了三个“考点”(计数,背包dp,逆元),其实背包dp以及求逆 ...
- jquery选择器大全参考
在Dom 编程中我们只能使用有限的函数根据id 或者TagName 获取Dom 对象. 然而在jQuery 中则完全不同,jQuery 提供了异常强大的选择器用来帮助我们获取页面上的对象, 并且将对象 ...
- 如何在oracle中导入导出dmp数据库文件
Oracle数据导入导出imp/exp就相当于oracle数据还原与备份.exp命令可以把数据从远程数据库服务器导出到本地的dmp文件,imp命令可以把dmp文件从本地导入到远处的数据库服务器中.利用 ...
- SpringBoot | 第五章:多环境配置
前言 写上一篇看英文资料,耗费了心力呀,这章,相对来说简单点.也比较熟悉,但是这很实用.不扯了,开始~ 多环境配置 maven的多环境配置 springboot多环境配置 总结 老生常谈 多环境配置 ...
- 小程序的switch组件
小程序的switch开关组件,总结下大概有三种使用场景. 其一: 纯展示场景, 用来展示某个开关值是打开还是关闭的,这个场景比较简单,给个disabled属性就ok了: 其二: 用户点击后立即切换开关 ...
- java关于类的构建
一开始老是把类的构建和代码的重构搞的混淆,现在理解的可能还好点(至少概念上不会出错了),简单的说类就是一个复杂的变量,这个变量里面含有属性.方法和构造方法,注意方法和构造方法是完全不同的两个概念,而且 ...
- javascript实现多线程提升项目加载速度
以前大家都认为js是单线程执行的,假如我们要执行一些耗时的操作,比如加载一张很大的图片,我们可能需要一个进度条来让用户进行等待,在等待的过程中,整个js线程会被阻塞,后面的代码不能正常运行,这可能大大 ...
- 牛客NOIP提高组(三)题解
心路历程 预计得分:$30 + 0 + 0 = 30$ 实际得分:$0+0+0= 0$ T1算概率的时候没模爆long long了... A 我敢打赌这不是noip难度... 考虑算一个位置的概率,若 ...
- Catch the moments of your life. Catch them while you're young and quick.
Catch the moments of your life. Catch them while you're young and quick.趁你还年轻利落,把握住生活中的美好瞬间吧!
- echarts折柱混合(图表数据与x轴对应显示)
一天24个小时,每个小时不一定都有对应的数据,所以后台给出的数据,只有每个时间点对应的数据,比如4点,给的是112,5点的242,其他时间没有,则只显示4点,5点时候的数据,那么现在对应的时间点就是后 ...