给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
示例 1:
输入: 1->2->3->3->4->4->5
输出: 1->2->5
示例 2:
输入: 1->1->1->2->3
输出: 2->3
法一、采用找重复之前和找重复之后,时间复杂度 O(n2) ----自己所写
1 class Solution { 2 public: 3 ListNode* searchPreDuplicates(ListNode *head, ListNode *p){ 4 ListNode* q = head; 5 while(q != NULL&& q->next != NULL){ 6 if(q->next == p) 7 break; 8 q = q->next; 9 } 10 return q; 11 } 12 ListNode* deleteDuplicates(ListNode* head) { 13 ListNode* preHead= new ListNode(-1); 14 ListNode *p = preHead; 15 p->next = head; 16 p = p->next; 17 //ListNode* p = head; 18 while(p != NULL && p->next != NULL){ 19 if(p->val != p->next->val){ 20 p = p->next; 21 } 22 else{ 23 ListNode* pre = searchPreDuplicates(preHead,p); 24 25 while(p != NULL && p->next != NULL && p->val == p->next->val) p = p->next; 26 //找重复数字的下一个节点 27 28 ListNode* post = p->next; 29 30 31 pre->next = post; 32 p = post; 33 34 } 35 } 36 return preHead->next; 37 } 38 };
法二、采用快慢指针,时间复杂度O(n)-----学习他人
1 class Solution { 2 public: 3 4 ListNode* deleteDuplicates(ListNode* head) { 5 //创建哑节点 6 ListNode *preHead = new ListNode(-1); 7 preHead->next = head; 8 //创建快慢指针 9 ListNode *slow = preHead; //慢指针用于指向重复数字的前一个数字 10 ListNode *fast = head; //快指针用于寻找重复数字 11 12 while(fast != NULL && fast->next != NULL){ 13 if(fast->val != fast->next->val){ //分情况讨论,如1->2和1->1->2 14 if(slow->next == fast ) //此时之前没有重复数字 15 slow = fast; 16 else{ 17 slow->next = fast->next; //此时将略过重复数字 18 } 19 } 20 fast = fast->next; 21 } 22 23 if(slow->next != fast) slow->next = fast->next; 24 25 return preHead->next; 26 27 } 28 };
此方法不能忽略最后的[1,1]情况判断,即上面第23行很关键。因为快慢指针是前后挨着。若输入的数据全部是重复数字,那么相当于fast指针一直前进,没有执行更新slow指针的值(第17行)
就跳出循环,所以最后再更新slow指针的值。
1.本题重复数字在开头的处理方法为 : 哑节点
2.学习了对于链表设置快慢指针的方法,此方法的实质依旧是未重复数字之前的数字指向重复完成数字之后,只不过实现时用到了双指针
原文:https://www.cnblogs.com/fresh-coder/p/12989894.html