给定一个已排序的链表的头 head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
提示:
- 链表中节点数目在范围
[0, 300]
内 -100 <= Node.val <= 100
- 题目数据保证链表已经按升序 排列
【方法一】单指针
第一步:如果头节点和头节点的下一个节点为空,则返回头结点。
第二步:创建一个指针p指向头指针。
第三步:如果头节点和头节点的下一个节点不为空,判断头节点和头节点下一个节点的数据是否相等(由题目可以知道,链表的第一个节点为头节点,且头结点中含有数据),如果相等,将p的后继指针指向p的后继的后继(相当于删除重复的后面那个数据);如果不相等,p指针移动到p的后继(相当于向后遍历)。
第四步:返回最后删除后的链表。
具体案例分析:
head=[1,1,2,3,3]
开始时,p指向第一个节点1(也就是head),判断p的后继和p中的数据是否相等。相等则将p的后继指针指向p的后继的后继(也就是指向2);然后进行下一轮判断,此时p指向1,p的后继指向2,不相等,则p指针移动到p的后继(也就是说现在p指向2);继续进行后面判断.............
C语言具体代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* deleteDuplicates(struct ListNode* head){
if(head==NULL || head->next==NULL){
return head;
}
struct ListNode* p = head;
while (p != NULL && p->next != NULL)
if (p->val == p->next->val){
p->next = p->next->next;
}
else {
p = p->next;
}
return head;
}
时间复杂度O(n);空间复杂度O(1)
【方法二】双指针
第一步:如果头节点和头节点的下一个节点为空,则返回头结点。
第二步:创建一个指针p指向头指针和一个移动指针q。
第三步:如果头节点和头节点的下一个节点不为空,判断头节点和头节点下一个节点的数据是否相等(由题目可以知道,链表的第一个节点为头节点,且头结点中含有数据),如果相等,将q指针指向p指针的下一个节点,将p的后继指针指向p的后继的后继,然后释放掉q指针free(q)(相当于删掉重复的数据,也就是q指针所指的),如果不相等,p指针移动到p的后继(相当于向后遍历)。
第四步:返回最后删除后的链表。
具体案例分析:
head=[1,1,2,3,3]
开始时,p指向第一个节点1(也就是head),判断p的后继和p中的数据是否相等。如果相等,将q指针指向p的后继(也就是第二个1),然后将p的后继指针指向p的后继的后继,最后释放掉q(也就是删掉第二1)。然后进行下一轮判断,此时p指向1,p的后继指向2,不相等,则p指针移动到p的后继(也就是说现在p指向2);继续进行后面判断.............
C语言具体代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* deleteDuplicates(struct ListNode* head){
if(head==NULL || head->next==NULL){
return head;
}
struct ListNode *p = head;
struct ListNode *q ;
while (p != NULL && p->next != NULL) {
if (p->next->val == p->val) {
q = p->next;
p->next = p->next->next;
free(q);
} else {
p = p->next;
}
}
return head;
}
时间复杂度O(n);空间复杂度O(1)