题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5
数据范围:链表长度满足 0≤n≤1000 0≤n≤1000 ,链表中的值满足 1≤val≤1000 1≤val≤1000
进阶:空间复杂度 O(n) O(n) ,时间复杂度 O(n) O(n)
例如输入{1,2,3,3,4,4,5}时,对应的输出为{1,2,5},对应的输入输出链表如下图所示:
示例1
输入:{1,2,3,3,4,4,5} 返回值:{1,2,5}
示例2
输入:{1,1,1,8} 返回值:{8}
题目解析
首先审视一下题目,
链表是有序的:重复节点在链表中是连续出现的,这意味着我们可以利用链表的有序性来简化判断是否存在重复节点。
重复节点不保留:对于连续出现的重复节点,既要删除这些节点,又要保持链表的连接性。
返回链表头指针:最终结果是一个新的链表,删除重复元素后的链表头指针。
解题思路
根据题目要求,基本思路是使用双指针遍历链表,通过比较相邻节点的值来判断是否有重复,一个指针用来遍历链表,当出现值相等的两个节点则判断出现重复节点,需要调用另一个指针跳过,另一个指针用来跟踪不重复的最后一个节点,遍历链表的指针删除时需要特别注意处理头节点可能会被删除的情况。
代码实现
我们先创建一个哨兵节点,它指向链表的头节点。这样可以简化链表头节点被删除的特殊情况处理。
val dummy = ListNode(0)
dummy.next = pHead
再使用双指针遍历链表,指针 prev
用来跟踪不重复的最后一个节点,current
用来遍历整个链表。每当 current
和 current.next
的值相等时,说明有重复节点出现,我们要跳过这些节点。
object Solution {
fun deleteDuplication(pHead: ListNode?): ListNode? {
val dummy = ListNode(0)
dummy.next = pHead
var prev: ListNode? = dummy
var current = pHead
while (current != null) {
// 如果当前节点和下一个节点值相同,跳过所有重复节点
if (current.next != null && current.`val` == current.next.`val`) {
// 找到最后一个重复节点
while (current?.next != null && current.`val` == current.next?.`val`) {
current = current.next
}
// 跳过所有重复节点
prev?.next = current?.next
} else {
prev = prev?.next
}
current = current?.next
}
return dummy.next
}
}
如果发现了重复节点,prev.next
指向 current
的下一个节点,直接跳过重复的部分。否则,prev
移动到下一个节点,继续检查。