- 递归法
链表具有天然的递归性,凡是链表的问题我们都可以考虑一下递归,可以把一个链表看成头节点后挂接一个更短的链表,这个更短的链表看成其的头节点后面挂接一个更更短的链表,依次类推。所以可以先处理头节点后面挂接的更短的链表,处理完之后,判断头节点的值是否等于其挂接的更短的链表的头节点的值,如果相等则直接返回更短的链表的头节点,否则返回原链表的头节点。
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if not head or not head.next: return head
head.next = self.deleteDuplicates(head.next)
return head.next if head.val == head.next.val else head
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (head == NULL || head->next == NULL) {
return head;
}
// 删除头节点后面挂接的链表中的重复元素
head->next = deleteDuplicates(head->next);
// 头节点与后面挂接的链表中的节点值相同,则头节点也删除,否则不删除
return head->val == head->next->val ? head->next : head;
}
};
- 单指针
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if not head or not head.next: return head
cur = head
while cur and cur.next:
if cur.val == cur.next.val:
cur.next = cur.next.next
else: cur = cur.next
return head
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (head == NULL || head->next == NULL) { // 特判
return head;
}
ListNode* cur = head; // 当前节点
while (cur != NULL && cur->next != NULL) { // 一直遍历,直到当前节点为空或者当前节点是尾节点
if (cur->val == cur->next->val) { // 当前节点的值与其后继节点的值相同,则删除当前节点的后继节点
cur->next = cur->next->next;
} else { // 否则继续遍历
cur = cur->next;
}
}
return head;
}
};
- 双指针
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if head is None or head.next is None: return head
cur, next = head, head.next
while cur and next:
if next.val != cur.val: cur = cur.next
else: cur.next = next.next
next = next.next
return head
这里双指针解法其实逻辑上比单指针更加复杂,我一开始犯了一个低级错误,当cur和next的值相等时直接各往后跳两位,这样是不对的,会导致一些重复值被跳过了。