题目描述

题解
//////////////////////////////// 双指针 ////////////////////////////
// 牛客
// 运行时间:14ms
// 占用内存:9916k
public class Solution{
public ListNode deleteDuplication(ListNode pHead) {
if (pHead == null || pHead.next == null)
return pHead
ListNode dummy = new ListNode(-1)
dummy.next = pHead
ListNode pre = dummy
ListNode cur = pHead
cur = cur.next
while (cur != null) {
// 如果发现重复结点
if (pre.next.val == cur.val) {
if (cur.next == null) { // 判断cur右移后是否到达链表尾
pre.next = null
break
}
cur = cur.next
// 如果右移后cur到达重复子串的尾部
if (pre.next.val != cur.val) {
pre.next = cur
cur = cur.next
}
}
// 未发现重复结点,一起右移
else {
pre = pre.next
cur = cur.next
}
}
return dummy.next
}
}
// 简化版
// 运行时间:14ms
// 占用内存:9984k
public class Solution{
public ListNode deleteDuplication(ListNode pHead) {
if (pHead == null || pHead.next == null)
return pHead
ListNode dummy = new ListNode(-1)
dummy.next = pHead
ListNode pre = dummy
ListNode cur = pHead
while (cur != null) {
// 如果发现重复结点
if (cur.next != null && cur.next.val == cur.val) {
while (cur.next != null && cur.next.val == cur.val) {
cur = cur.next
}
// 再前进一格
cur = cur.next
pre.next = cur
}
// 未发现重复结点,一起右移
else {
pre = pre.next
cur = cur.next
}
}
return dummy.next
}
}
/////////////////////////////////// 递归法 //////////////////////////
// 牛客
// 运行时间:11ms
// 占用内存:9948k
public class Solution {
public ListNode deleteDuplication(ListNode pHead) {
// 未开始递归时,pHead是头结点,开始递归后,pHead为遍历结点
if (pHead == null || pHead.next == null) {
return pHead;
}
// 1.未开始递归时,取头结点next记为next
// 2.开始递归后,pHead为遍历节点,且实际被pHead.next指向,
// next为pHead.next,所以实际被pHead.next.next指向
ListNode next = pHead.next;
// 1.未开始递归时,若头结点出现重复,则if成立,
// 直接开始while循环找重复子串尾结点
// 2.开始递归后,如果pHead和next的val相等
// 开始while循环找重复子串尾结点
if (pHead.val == next.val) {
// while循环继承了if的判断,同时保证next(pHead.next.next)不为null
while (next != null && pHead.val == next.val)
next = next.next; // next右移,直到遍历到重复子串的下一个结点
// 返回deleteDuplication递归调用
// 递归到底并返回之后,由于next被pHead.next指向,所以
// next循环右移就已经剔除了重复结点
return deleteDuplication(next);
}
// 若头结点未出现重复,else成立
else {
// 令pHead.next指向eleteDuplication的递归调用,输入pHead.next
// 假设链表一直没有重复节点,函数输入pHead实际是被上一个递归
// 的pHead.next指向,再递归取pHead.next,对于上一次递归
// 就是pHead.next.next,一直这样下去,实际就是遍历了整个
// 链表一次。
pHead.next = deleteDuplication(pHead.next);
return pHead;
}
}
}