前几天链表题吃了亏…来练点链表题,顺便也要天梯赛了…
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。
返回同样按升序排列的结果链表。
思路: 一开始想着用一个循环一路碰到相等节点直接删过去的,但是碰到链表也没想到怎么写。最后看了眼别人说递归…然后想了下确实更好写
1、需要删除的情况:递归将头结点直接指向第一个不相等的节点;
2、不需要删除的情况:递归查找头结点的下一个节点;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head==nullptr||head->next==nullptr) {
return head;
}
ListNode* tmp=head->next;
if(head->val==tmp->val) {
while(tmp!=nullptr&&tmp->val==head->val) {
tmp=tmp->next;
}
head=deleteDuplicates(tmp);
} else {
head->next=deleteDuplicates(tmp);
}
return head;
}
};
看到了一种维护窗口的做法:
通过维护两个指针,用第一个指针作为前置,第二个指针探点,当第二个指针的next指向的值与当前指向值相同时,一直向后推,找到不相同的情况,然后用前置指针直接指向不同的节点,相当于删除这部分重复的节点。
需要注意的是需要先将一个节点作为头指针之前的节点,用于在情况:(1->1->1->2->3)时指向删除后的头指针(2)。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode *pre=new ListNode;
ListNode *cer=head;
ListNode *before=pre;
pre->next=head;
while(cer!=nullptr&&cer->next!=nullptr) {
if(cer->next->val==cer->val) {
while(cer->next!=nullptr&&cer->next->val==cer->val) {
cer=cer->next;
}
pre->next=cer->next;
cer=pre->next;
} else {
pre=cer;
cer=cer->next;
}
}
return before->next;
}
};