链表去重 82
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。返回同样按升序排列的结果链表
在这里插入图片描述
思路:因为是已经排好序的链表所以只需要比较前后就知道该节点的值是否是重复
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* deleteDuplicates(struct ListNode* head){
if(head==0||head->next==0) return head;
int val=head->val;
struct ListNode *p=head;
struct ListNode *pn=p->next->next; //下个
struct ListNode *pre=head; //前面的一个
struct ListNode *ln=0; //返回链表的尾
p=p->next;
if(p->val!=pre->val) ln=head; //尝试确定表头
while(pn){
while(pn&&(p->val==pre->val||pn->val==p->val)){ //比较跟之前跟后面的是否一样
pre=pre->next;
p=p->next;
pn=pn->next;
}
if(pn){ //如果是因为下个为空结束,那么结束循环,否则将p加入新链表
pn=pn->next;
}else{
break;
}
if(ln==0){ //若队首确定了则加入,否则新加入的为表头
ln=p;
head=ln;
}else{
ln->next=p;
ln=ln->next;
}
pre=pre->next;
p=p->next;
}
if(pre->val!=p->val){ //看看最后一个符不符合要求
if(ln==0){
ln=p;
head=ln;
}else{
ln->next=p;
ln=ln->next;
}
}
if(ln==0) return ln; //如果表头仍为空 返回
ln->next=0;
return head;
}
删除链表重复元素,力扣83
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。返回同样按升序排列的结果链表
这题跟上面的区别在于,需要保留重复元素,采用类似于队列的思想,将新的元素跟队尾的元素相比较如果在队尾中那么去寻找下一个,如果跟队尾元素不相等,则将节点加入。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* deleteDuplicates(struct ListNode* head){
if(head==0) return head;
struct ListNode* pre=head; //pre为队尾节点
struct ListNode* p=pre->next;
while(p){
while(p&&p->val!=pre->val){ //如果p不为空节点,且p不和队尾相等则就把p节点加入
pre->next=p;
p=p->next;
pre=pre->next;
}
if(p==0) break; 如果p等于0 ,则结束
p=p->next;
}
pre->next=0;
return head;
}
总结:在处理链表类问题的时候存在的一些问题:1)空节点问题,因为表头可能为空要注意
2)在新生成的链表的时候,队尾节点的next一定要设为空
3)在追加节点的时候p=p->next 也不能忘记
4) malloc 的资源需要释放