问题描述:
给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
例如:给出的链表为1 \to 2\to 3\to 3\to 4\to 4\to51→2→3→3→4→4→5, 返回1\to 2\to51→2→5.
给出的链表为1\to1 \to 1\to 2 \to 31→1→1→2→3, 返回2\to 32→3.
例如:给出的链表为1 \to 2\to 3\to 3\to 4\to 4\to51→2→3→3→4→4→5, 返回1\to 2\to51→2→5.
给出的链表为1\to1 \to 1\to 2 \to 31→1→1→2→3, 返回2\to 32→3.
数据范围:链表长度 0 \le n \le 100000≤n≤10000,链表中的值满足 |val| \le 1000∣val∣≤1000
要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n);进阶:空间复杂度 O(1),时间复杂度 O(n)
题目已经说明给定的链表是有序的,所以找重复出现的值是很简单的,只需要从头到
尾遍历链表:如果head->val==head->next->val,说明出现重复值。
根据题目说明需要删除所有重复值,那么就需要获得该重复值的前驱pre,这样循环找
到第一个不重复的值,让pre指针指向该节点就行了。
但是又有一个问题,如果链表第一个节点就出现重复值怎么办,第一个节点没有前驱。
所以我们就需要创建一个新节点Nhead,并且让Nhead->next=head。同时让前驱一开始
指向Nhead。最后返回Nhead->next就行了。
那么接下来我们需要做的就是:
1:head->val<head->next->val :pre=head,head=head->next
2:head->val==head->next->val :循环找到第一个与当前值不同的节点,然后
pre->next=head.
复杂度分析:
时间复杂度:O(n),因为只需要让head一直遍历到尾就行了。
空间复杂度:O(1),常数个变量。
/** * struct ListNode { * int val; * struct ListNode *next; * }; */ class Solution { public: ListNode* deleteDuplicates(ListNode* head) { if(head==NULL||head->next==NULL) return head; ListNode *Nhead=(ListNode*)malloc(sizeof(ListNode)); Nhead->next=head; ListNode* pre=Nhead; int n; while(head!=NULL&&head->next!=NULL) { if(head->val<head->next->val) pre=head,head=head->next; else { n=head->val; head=head->next; while(head!=NULL&&head->val==n) head=head->next; pre->next=head; } } return Nhead->next; } };