算法题15:删除有序链表中重复的元素
1、第一类
删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次。
代码
ListNode* deleteDuplicates(ListNode* head) {
// write code here
if(head==NULL || head->next==NULL) return head;
ListNode *pre = head;
ListNode *cur = head->next;
while(cur!=NULL){
// 如果结点值与前一个结点值相同,删除当前结点
if(cur->val == pre->val){
pre->next = cur->next;
cur = pre->next;
}
else{
cur = cur->next;
pre = pre->next;
}
}
return head;
}
2、第二类
给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
思路
- 在第一类问题的基础上,需要删除所有重复元素的第一个结点,因此将pre和cur指针的位置向前移动一位,初始时将pre设置为新的头结点,防止第一个结点就出现重复从而将原head结点删除的情况出现;
- 比较cur和cur->next结点的值,如果相等则删去重复的结点,即cur->next结点,并记录repeat为true,进行下一轮循环;
- 当cur和cur->next结点的值不等时,需要判断是否存在repeat,如果存在,说明当前cur结点为重复结点,需要删去;如果不存在,则pre和cur依次移位,进入下一轮循环;
- 最后需要单独处理最后一个结点。
代码
ListNode* deleteDuplicates(ListNode* head) {
// write code here
if(head==NULL || head->next==NULL) return head;
ListNode *pre = new ListNode(0); //添加一个表头结点,防止将原链表的头结点删除而无法输出链表
pre->next = head;
head = pre; //新的头结点
//ListNode *pre = NULL; //前一个结点,为了删除第一个重复的结点
ListNode *cur = head; //当前结点
bool repeat = false; //当前结点是否发生重复
while(cur->next != NULL){
if(cur->next->val == cur->val){
cur->next = cur->next->next; //删除后面重复的结点
repeat = true;
}
else if(repeat){
pre->next = cur->next; //删除第一个重复结点
cur = pre->next;
repeat = false;
}
else{
pre = cur;
cur = cur->next;
}
}
// 处理最后一个结点
if(repeat){
if(pre==NULL) return NULL;
else pre->next = cur->next;
}
return head->next;
}