对排序数组中重复元素的删除操作,这里分两种情况,一种是重复的元素合并,另一种是重复元素的删除。先从简单的做起:合并
Given a sorted linked list, delete all duplicates such that each element appear only once.
For example,
Given1->1->2
, return1->2
.Given1->1->2->3->3
, return1->2->3
.
这个就跟数组中重复元素合并差不多,只需要考虑当前节点与下一个节点的关系。
只需要判断当前节点与下一个节点是否相等,不等则把前节点接上目标链表中,这种不等除了值以外,还包括下一个节点为空的情况。
为了操作方便,代码中用到一个虚构的链表头用以辅助操作,代码如下:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution {10 public:11 ListNode *deleteDuplicates(ListNode *head) {12 ListNode vhead(0);13 vhead.next = head;14 ListNode* pre = &vhead;15 ListNode* p = pre->next;16 while (p != NULL) {17 if (p->next == NULL || p->next->val != p->val) {18 pre->next = p;19 pre = p;20 }21 p = p->next;22 }23 return vhead.next;24 }25 };
那删除重复元素又有什么区别呢?
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given1->2->3->3->4->4->5
, return1->2->5
.Given1->1->1->2->3
, return2->3
.
我们需要把重复的删掉。
首先要记录上次删掉的顶点deleted,初始为NULL。
当遇到当前节点与下一节点重复时,我们在跳过前还需要把重复的节点记录到deleted中。
当前节点与下一节点不重复且deleted与当前节点值不重复,那么就把当前节点与目标链表接上。
到最后一个节点时,也作同样判断,不同的是判断到有重复时,需要在目标链表结尾处补上一个NULL。
以上的条件还是需要仔细想想的,LZ表示考虑了很久才化简到个人认为比较容易理解的条件了。看代码:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution {10 public:11 ListNode *deleteDuplicates(ListNode *head) {12 ListNode vhead(0);13 vhead.next = head;14 ListNode* deleted = NULL;15 ListNode* pre = &vhead;16 ListNode* p = pre->next;17 while (p != NULL) {18 if (p->next != NULL) {19 if (p->val == p->next->val) {20 deleted = p;21 } else {22 if (deleted == NULL || p->val != deleted->val) {23 pre->next = p;24 pre = p;25 } 26 }27 } else {28 if (deleted == NULL || p->val != deleted->val) {29 pre->next = p;30 } else {31 pre->next = NULL;32 }33 }34 p = p->next;35 }36 return vhead.next;37 }38 };