Given a sorted linked list, delete all duplicates such that each element appear only once.(给定一个有序链表,删除所有的重复元素,使得所有元素都是唯一的)
For example,
Given 1->1->2, return 1->2.
Given 1->1->2->3->3, return 1->2->3.
1.个人分析
之前遇到过类似的问题,只不过这里给出的是有序链表,而且也没有要求只能在原序列中操作,所以就不用自己去先排序,这里可以使用一个额外的链表来保存最终结果,或者双指针的方法进行处理。
思路:
(1)设立两个指针p1,p2,用p1始终指向新链表的尾部节点,而p2用来遍历p1之后的所有节点
(2)如果p2指向的节点与p1指向的节点不同,则将p2指向的元素复制到p1的后一个位置,然后将p1后移一位,否则p2就继续往后遍历,直到遍历完成。
(3)使p1->next=NULL,释放p1之后所有节点的空间。
2.个人解法
(1)覆盖之后再删除
ListNode* deleteDuplicates(ListNode* head)
{
if(!head || head->next == NULL)
return head;
ListNode *p1, *p2;
p1 = head;
p2 = p1->next;
while(p2)
{
if(p1->val != p2->val){
p1->next->val = p2->val;
p1 = p1->next;
}else{
p2 = p2->next;
}
}
p2 = p1->next;
p1->next = NULL;
ListNode *tmp = NULL;
while(p2)
{
tmp = p2;
p2 = p2->next;
delete tmp;
}
return head;
}
(2)边修改指针边删除
ListNode* deleteDuplicates(ListNode* head)
{
if(!head || head->next == NULL)
return head;
ListNode *p1, *p2, *tmp;
p1 = head;
p2 = p1->next;
while(p2)
{
if(p1->val == p2->val){
p1->next = p2->next;
tmp = p2;
delete tmp;
}else{
p1 = p2;
}
p2 = p2->next;
}
return head;
}
3.参考解法
public ListNode deleteDuplicates(ListNode head) {
ListNode current = head;
while (current != null && current.next != null) {
if (current.next.val == current.val) {
current.next = current.next.next;
} else {
current = current.next;
}
}
return head;
}
该解法是Java实现的,思想是从头到尾遍历一次有序链表,如果两相邻节点值相同,就将当前节点的next指向下下个节点,当遍历结束时,链表中也就不含重复的节点了。这种解法是利用了有序的特性,否则就无法使用该法来解决。
4.总结
个人解法中的第一种解法是来源于从一个数组中去除重复元素,采用双指针方法,但该方法需要在最后删除新链表之后的节点,所以效率上会比第二种方法低一些。另外自己在LeetCode中尝试了一下不进行手动delete操作,虽然也能AC,但这样在实际中极有可能造成内存泄露的。
PS:
- 题目的中文翻译是本人所作,如有偏差敬请指正。
- 其中的“个人分析”和“个人解法”均是本人最初的想法和做法,不一定是对的,只是作为一个对照和记录。