描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
示例
input1:
{1,2,3,3,4,4,5}
output1:
{1,2,5}
思路
本题需要去除重复的结点,因此可以借助辅助空间,或者直接在原链表上操作
1、借助辅助空间
在这里,我们可以使用两次遍历:第一次遍历用HashMap
来存储重复结点的数字和出现的次数,第二次遍历剔除链表中含有重复的结点
import java.util.*;
public class Solution {
public ListNode deleteDuplication(ListNode pHead) {
if(pHead == null) return pHead;
HashMap<Integer, Integer> map = new HashMap<>();
ListNode pre = pHead, nex;
while(pre != null){
map.put(pre.val, map.get(pre.val) == null? 1 : map.get(pre.val)+1);
pre = pre.next;
}
pre = pHead;
while(pre != null){
nex = pre.next;
while(nex != null && map.get(nex.val) > 1) nex = nex.next;
pre.next = nex;
pre = nex;
}
//注意:上面的循环不会剔除pHead结点,因此此处需要手动判断
return map.get(pHead.val) == 1 ? pHead : pHead.next;
}
}
2、直接在原链表上操作
由于可能存在pHead
结点重复,因此手动在pHead
结点前建立一个头节点,沿着该头节点逐步排查重复的结点段
public class Solution {
public ListNode deleteDuplication(ListNode pHead) {
if(pHead == null || pHead.next == null) return pHead;
ListNode head = new ListNode(0);
head.next = pHead;
/** pre -> tmp -> nex **/
ListNode pre = head, tmp = head.next, nex = tmp;
while(tmp != null){
while(nex != null){
nex = tmp.next;
//找出值和tmp结点不同的结点,使用nex指向该节点
while(nex != null && tmp.val == nex.val) nex = nex.next;
//tmp结点元素有重复时,则跳过这一段重复的结点,同时判断下一段结点是否重复
if(tmp.next != nex) tmp = nex;
else break;
}
pre.next = tmp;
pre = tmp;
if(pre != null) tmp = pre.next;
}
return head.next;
}
}
3、递归的解法
在本题中,根据当前结点是否重复分为两种情况:
(1)当前结点重复时,那么往下遍历跳过与当前节点重复的全部节点,找到第一个与当前节点不同的节点;相当于丢弃重复结点,从找到的结点进行递归
(2)当前结点不重复时,保留当前结点,从下一个结点继续递归
由于本题种需要用到当前结点的下一个结点来判断与当前结点是否重复,因此出口条件可以设置为:
if(pHead == null || pHead.next == null) return pHead
public class Solution {
public ListNode deleteDuplication(ListNode pHead) {
if(pHead == null || pHead.next == null) return pHead;
if(pHead.next.val == pHead.val){
ListNode tmp = pHead.next;
while(tmp != null && tmp.val == pHead.val) tmp = tmp.next;
return deleteDuplication(tmp);
}
else{
pHead.next = deleteDuplication(pHead.next);
return pHead;
}
}
}