C/C++ BM16 删除有序链表中重复的元素-II
前言
这道题和BM15稍有些差别,一开始做的时候还是按照BM15的方法来做,结果想了半天发现自己路走窄了。
这道题也是删除节点的方式,不过可能出现删除或者说跳过节点数不固定的情况,这种情况在处理的时候,我一开始用一个变量来保存要处理的节点个数,最后发现,这样做很麻烦,要考虑多种情况。
题目
描述
给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
例如:
给出的链表为
1
→
2
→
3
→
3
→
4
→
4
→
5
1→2→3→3→4→4→5
1→2→3→3→4→4→5, 返回
1
→
2
→
5
1→2→5
1→2→5
给出的链表为
1
→
1
→
1
→
2
→
3
1→1→1→2→3
1→1→1→2→3 返回
2
→
3
2→3
2→3.
数据范围:链表长度
0
≤
n
≤
10000
0≤n≤10000
0≤n≤10000,链表中的值满足
∣
v
a
l
∣
≤
1000
∣val∣≤1000
∣val∣≤1000
要求:空间复杂度
O
(
n
)
O(n)
O(n),时间复杂度
O
(
n
)
O(n)
O(n)
进阶:空间复杂度
O
(
1
)
O(1)
O(1),时间复杂度
O
(
n
)
O(n)
O(n)
示例1
输入:{1,2,2}
返回值:{1}
示例2
输入:{}
返回值:{}
解决方案一
1.1 思路阐述
对于BM15来说,始终要保留一个节点,但是BM16里面,凡是相同的节点,都要删除。这就会出现第一个节点就要删除的情况。
所以我们在处理节点的时候需要知道删除节点的前驱节点,因此在整个链表中需要一个表头,作为初始链表的前驱结点。
因为删除的节点可能不止两个,会有更多的重复,所以需要跳过相同的节点,找到下一个不同的节点,这就涉及到新的循环判断。
最后返回的链表应该是自己添加的表头的下一个节点开始的链表。
具体做法:
step 1:给链表前加上表头,方便可能的话删除第一个节点。
step 2:遍历链表,每次比较相邻两个节点,如果遇到了两个相邻节点相同,则新开内循环将这一段所有的相同都遍历过去。
step 3:在step 2中这一连串相同的节点前的节点直接连上后续第一个不相同值的节点。
step 4:返回时去掉添加的表头。
1.2 源码
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
//空链表
if(head == NULL)
return NULL;
ListNode* res = new ListNode(-1);
//在链表前加一个表头
res->next = head;
ListNode* cur = res;
while(cur->next != NULL && cur->next->next != NULL){
//遇到相邻两个节点值相同
if(cur->next->val == cur->next->next->val){
int temp = cur->next->val;
//将所有相同的都跳过
while (cur->next != NULL && cur->next->val == temp)
cur->next = cur->next->next;
}
else
cur = cur->next;
}
//返回时去掉表头
return res->next;
}
};
总结
BM15与BM16属于同类型问题,BM16是进阶。
这类问题主要在于删除节点的操作,链表中删除节点涉及到当前节点的删除和下一个节点的删除大致这两种情况。
当前节点的删除的话,需要知道当前节点的前驱结点,所以在一开始就要有一个前驱结点对应的指针。
下一个节点删除的话,因为是下一个节点,所以当前节点就是下一个节点的前驱结点,因此这种删除比较方便。
原文地址:https://blog.csdn.net/Edwinwzy/article/details/136154014
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!