今天给大家分享一道字节跳动的面试题,也就是 Leetcode 83. 删除排序链表中的重复元素,提供三种(递归、迭代(单指针、双指针))解题思路,供大家参考。
题目
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例 1:
输入: 1->1->2
输出: 1->2
示例 2:
输入: 1->1->2->3->3
输出: 1->2->3
递归解法
解题思路:在上上期的面试不可不会的单链表反转中,提到了针对链表的题目可以采用递归的思想去解答,其主要的思想:把链表看成头节点后面挂接一个更短的链表,这个更短的链表的头节点是原链表的第二个节点,更短的这个链表又可以看成是当前链表的头节点后面再挂接一个更更短的链表,这个更更短的链表的头节点是原链表的第三个节点,依次类推。以链表1->2->3->4为例,具体如下图示:
有了上面的分析,可以先删除更短的链表(或者更更短的链表)中的重复元素,然后再判断头节点的值是否跟删除后更短链表的头节点值是否相等,相等则将头节点也删除,否则把删除后更短链表挂接在头节点的后面。以链表1->1->2->3->3 为栗子,如下图示:
Show me the Code
// C 语言struct ListNode* deleteDuplicates(struct ListNode* head){ if (head == NULL || head->next == NULL) { return head; } /* 删除头节点后面挂接的更短的链表中的重复元素 */ head->next = deleteDuplicates(head->next); /* 头节点与后面挂接的链表中的头节点的值相同,则删除头节点,否则不删除 */ return head->val == head->next->val ? head->next : head;}
// go 语言func deleteDuplicates(head *ListNode) *ListNode { if head == nil || head.Next == nil { return head } head.Next = deleteDuplicates(head.Next) if head.Val == head.Next.Val { head = head.Next } return head}
迭代单指针解法
解题思路:由于题目已说明链表是排序链表,所以只需要遍历整个链表,然后挨个比较相邻节点的值是否相等,相等则通过将当前节点指向其下下个节点的方式去删除其下一个节点(重复元素)。
Show me the Code
// javaclass 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; }}
#python3class 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
迭代双指针解法
解题思路:定义两个指针,分别指向头节点和头节点的下一节点,移动这两个指针去遍历整个链表;边遍历边比较两个指针指向的节点的值是否相等,相等则将当前节点就指向其下下个节点(相当于删除其下一节点),然后继续遍历,否则不处理,遍历直到遍历完整个链表。
以链表 1->2->3->3->4->NULL 为栗子,如下图所示:
Show me the Code
// C++class Solution {public: ListNode* deleteDuplicates(ListNode* head) { if (head == NULL || head->next == NULL) { return head; } ListNode* cur = head; ListNode* next = head->next; while (next != NULL && cur != NULL) { /* 当前节点的值不等于其下一节点的值,则继续遍历,否则删除其下一节点 */ if (next->val != cur->val) { cur = cur->next; } else { cur->next = next->next; } /* 当前节点的下一节点不断移动,遍历整个链表 */ next = next->next; } return head; }};
// go 语言func deleteDuplicates(head *ListNode) *ListNode { if head == nil || head.Next == nil { return head } cur, next := head, head.Next for cur != nil && next != nil { if (cur.Val == next.Val) { cur.Next = next.Next } else { cur = cur.Next } next = next.Next } return head}