83:给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例 1:
输入: 1->1->2
输出: 1->2
示例 2:
输入: 1->1->2->3->3
输出: 1->2->3
解题思路:使用前继结点,和当前结点,当俩者相等时循环判断当前结点直到不相等。
ListNode* deleteDuplicates(ListNode* head) {
if (head == NULL || head->next == NULL)
return head;
ListNode* pPre = head; //前继结点
ListNode* pCur = head; //当前结点
ListNode* pDel = NULL;
while (pCur && pCur->next)
{
pCur = pCur->next;
if (pPre->val == pCur->val)
{
while (pCur && pPre->val == pCur->val)
{
pDel = pCur;
pCur = pCur->next;
pPre->next = pCur;
printf("delete:%d\n", pDel->val);
delete pDel;
pDel = NULL;
}
}
pPre = pCur;
}
return head;
}
82:
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
示例 1:
输入: 1->2->3->3->4->4->5
输出: 1->2->5
示例 2:
输入: 1->1->1->2->3
输出: 2->3
解题思路:这一题和上一题的区别就是重复了就要全部删除。相对于上一题难点就在于前继和当前结点都删除了,这个链表要怎么样接下去。最直接的思路就是再加一个前继结点不就完了,对,我就是这样想的。
根据示例1解题过程如下:
pPrepre=前前继结点 :p pPre = 前继结点 :e pCur = 当前结点 :c
p e c
首先指针是这样的:1->2->3->3->4->4->5
p e c
然后前移:1->2->3->3->4->4->5
这时候满足条件要开始删除,注意这里已经不能用c结点删除了因为e结点的那个3也要删除。还要想到一点就是c后面还有重复的,所以这里循环还c再走一下:while (pCur && pPre->val == pCur->val)pCur = pCur->next;。然后从e点删直到c点。
这时候注意不能让p点向前移了,不然就p e指向一个了。
p e c
1->2->4->4->5
p e c
1->2->5->null
ListNode* deleteDuplicates2(ListNode* head) {
if (head == NULL || head->next == NULL)
return head;
ListNode* pPrepre = head; //前前继结点
ListNode retHead(0);
retHead.next = head;
ListNode* pPre = head; //前继结点
ListNode* pCur = head; //当前结点
ListNode* pDel = NULL;
while (pCur && pCur->next)
{
pCur = pCur->next;
if (pPre->val == pCur->val)
{
while (pCur && pPre->val == pCur->val)
pCur = pCur->next;
while (pPre != pCur)
{
pDel = pPre;
pPre = pPre->next;
printf("delete:%d\n", pDel->val);
if (pDel == retHead.next)
{
retHead.next = NULL;
pPrepre = NULL;
}
delete pDel;
pDel = NULL;
}
if (pPrepre != NULL)
{
pPrepre->next = pPre;
}
else
{
retHead.next = pPre;
}
}
if (pPre != pCur) //2者相同说明刚刚执行了删除,前前继不用前移,不然就重合了
{
pPrepre = pPre;
}
pPre = pCur;
}
return retHead.next;
}