力扣83:
思路:利用双指针,fast遍历链表,slow指向所有去掉重复元素的链表,因为是1223->123,所以第一个结点一定保留,不用创建新的结点,slow和fast可以直接指向head。
public ListNode deleteDuplicates(ListNode head){
if(head==null) return null;
ListNode slow=head;
ListNode fast=head;
while(fast!=null){
if(fast.val!=slow.val){
slow.next=fast;
slow=slow.next;
}
fast=fast.next;
}
slow.next=null;
return head;
}
优化:实际上不需要双指针
public ListNode deleteDuplicates(ListNode head){
if(head==null) return null;
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;
}
力扣82:
思路:和上题不同在于重复的元素一个都不留,1223->13,为了防止第一个元素就是重复元素,需要创建新结点,同样是双指针,slow指向新结点,fast指向head。
方法一:哈希表
public ListNode deleteDuplicates(ListNode head){
if(head==null||head.next==null) return head;
HashMap<Integer,Integer> map=new HashMap<>();
ListNode node=head;
while(node!=null){
if(map.containsKey(node.val)){
map.put(node.val,map.get(node.val)+1);
}
else {
map.put(node.val,1);
}
node=node.next;
}
ArrayList<Integer> arr=new ArrayList<>();
for(Integer k:map.keySet()){
if(map.get(k)==1){
arr.add(k);
}
}
Collections.sort(arr);
ListNode res=new ListNode(0);
ListNode temp=res;
for(Integer i:arr){
ListNode p=new ListNode(i);
temp.next=p;
temp=temp.next;
}
return res.next;
}
方法二:双指针
public ListNode deleteDuplicates(ListNode head){
if(head==null||head.next==null) return head;
ListNode temp=new ListNode();
ListNode slow=temp;
ListNode fast=head;
temp.next=head;//这一步容易被忽略,因为要比较slow.next==fast,如果fast是链表第一个结点,要让slow.next!=null;
while(fast!=null){
while(fast.next!=null&&fast.val==fast.next.val){
fast=fast.next;
}//这时fast指向重复结点的最后一个
if(slow.next==fast){
slow=slow.next;
}
else {
slow.next=fast.next;//如果fast是链表最后一个结点,slow=null,因此不用执行slow.next=null;
}
fast=fast.next;
}
return temp.next;
}
public static ListNode deleteDuplicates(ListNode head){
if(head==null||head.next==null) return head;
ListNode res=new ListNode(0);
res.next=head;
ListNode a=res;
ListNode b=head.next;
while(b!=null){
if(a.next.val!=b.val){
a=a.next;
b=b.next;
}
else{
while(b!=null&&a.next.val==b.val){
b=b.next;
}
a.next=b;
b=b==null?null:b.next;
}
}
return res.next;
}
剑指18:删除链表的结点
public ListNode deleteNode(ListNode head, int val){
if(head.val==val) return head.next;//一般如果需要判断头结点需要创建临时结点,但是这里首先判断了所以可以直接令slow=head;
ListNode slow=head;
ListNode fast=head.next;
while(fast!=null&&fast.val!=val){
slow.next=fast;
slow=slow.next;
fast=fast.next;
}
if(fast!=null){
slow.next=fast.next;
}
return head;
}
相似题:力扣237
思路:将需要删除的结点的下一个复制,然后删除的是下一个结点
public void deleteNode(ListNode node) {
node.val=node.next.val;
node.next=node.next.next;
}
力扣19:删除链表的倒数第K个结点
public ListNode removeNthFromEnd(ListNode head, int n){
ListNode dummy=new ListNode(0);
ListNode pre=dummy;
dummy.next=head;
ListNode fast=head;
ListNode slow=head;
for(int i=0;i<n;i++){
fast=fast.next;
}
while(fast!=null){
slow=slow.next;
pre=pre.next;
fast=fast.next;
}
pre.next=slow.next;
return dummy.next;
}