在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5。
这是一道删除单链表中重复元素的题目,下面来进行暴力破解
思路:给两个指针slow和fast,slow用来标记当前节点,fast指向slow标记的节点后面一个位置的节点,用fast->val来和slow->val进行比较,不相等则fast直接往后走一步,如果相等则删除fast指向的节点,fast往后走一步,直到遍历完整个链表(注意删除完成后还需要删除slow指向的节点)。这样一轮下来就把一种重复出现的数字删除完了,但是还有别的数字,所以slow需要往后走一步,然后重复删除的步骤,所以需要两重嵌套循环,代码如下:
typedef struct ListNode List;
struct ListNode* deleteDuplication(struct ListNode* pHead ) {
// write code here
List *slow=pHead;
List *fast=pHead;
List *record=NULL;
List *record1=NULL;
int flag=0;
while(slow){
record=slow;
fast=slow->next;
while(fast){
if(slow->val==fast->val){
record->next=fast->next;
free(fast);
fast=record->next;
flag=1;
}else{
record=fast;
fast=fast->next;
}
}
if(pHead==slow&&flag){//处理pHead指向的节点就出现重复的情况
pHead=slow->next;
free(slow);
slow=pHead;
flag=0;
}else if(flag){//处理一般重复出现了的单个节点
record1->next=slow->next;
free(slow);
slow=record1->next;
flag=0;
}else{//没有重复出现过
record1=slow;
slow=slow->next;
}
}
return pHead;
}
因为每次删除一个节点都需要知道这个节点的地址,所以用slow和fast来进行遍历链表,用record和record1分别来记录slow和fast上一次指向的位置,用以删除节点。
上述代码中内部while循环用来删除和slow->val值相等的节点,删除后还需要删除slow指向的节点,所以才有了后面的代码。flag用来判断是否出现了重复情况,而重复出现的节点可能是第一个节点,这时候需要进行特殊处理,因为此时需要改变pHead的指向。而第一个节点的val值就只有两种情况,重复或者不重复,那么代码在执行时 if 和 else 里的语句一定在 elseif语句之前执行,那么这样就可以记录slow上一次指向的位置了,然后再继续循环,实现删除val值重复的所有节点。