题目描述
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
示例 1:
输入: 1->2->3->3->4->4->5
输出: 1->2->5
示例 2:
输入: 1->1->1->2->3
输出: 2->3
题目分析
删除链表和删除数组不同,麻烦的就是各个数之间的连接性。遍历链表就是用while循环。但是思路其实还是比较好想的。复制一下当前的值,往后查找有多少的相同的,跳过相同的连接后面的链表。
源码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head==null) return null;
ListNode dumhead=new ListNode(-1);
//创这个是为了保证及时head开始就有重复的,那我也能删除
dumhead.next=head;
ListNode cur=head;
ListNode pre=dumhead;
while(cur!=null&&cur.next!=null){
if(cur.val==cur.next.val){
int val=cur.val;
while(cur!=null&&cur.val==val){
cur=cur.next;
}
pre.next=cur;
}else{
pre=cur;
cur=cur.next;
}
}
return dumhead.next;
}
}
改进
还有一个方法其实差不多,但是比较巧妙,就是边循环边删除太难理解了,那么能不能我遍历完了再删除。其实是可以的,在遍历的过程中,我可以把遇到相同的数值赋值给-128(Integer范围是-128~127),然后再遍历一遍,把值为-128的删除。
改进代码
class Solution {
public ListNode deleteDuplicates(ListNode head) {
//判断链表是否为空
if(head == null) return null;
//新建一个虚拟头节点
ListNode dummy = new ListNode(-1);
//把虚拟头节点和链表连在一起
dummy.next = head;
ListNode current = head;
ListNode pNode;
//遍历寻找相同的值
while(current.next != null){
int val = current.val;
pNode = current.next;
//从非current指向的节点开始遍历这个val在其他节点是不是有
while(pNode != null){
//如果有,把两个相同的值赋-128,最后在链表中直接删除-128的值
if(val == pNode.val){
pNode.val = current.val = -128;
}
pNode = pNode.next;
}
//把current指针移到下一个节点,取值和其他节点进行对比
current = current.next;
}
//这里就是遍历操作删除值为-128的节点
ListNode c = dummy;
while((pNode = c.next)!= null){
if(pNode.val==-128){
c.next = pNode.next;
}else{
c = pNode;
}
}
return dummy.next;
}
}
分析
第一个时间复杂度为O(n^2)
第二个就是O(n^2),空间的复杂度第一个稍微高一点
难点
难点其实是删除链表而不是找相同的,做链表题最烦的也就是删除插入,因为要考虑连接性。而且对头和尾的处理都必须小心,一不小心就会出错。
小结
删除链表最好就要创建一个虚链表保存头,这样就不会有遗漏了,最后返回只要返回虚链表后面的就完成了。
[1]https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/submissions/