203、83、82 删除链表的某些节点

203 删除所有值为val的节点 Easy
m18 删除链表中值为val的节点,链表元素不重复 Easy
83 删除排序链表中的重复元素,重复只保留一个 Easy
82 删除排序链表中的重复元素,重复的都删掉 Medium
m2 删除排序链表中的重复元素,重复只保留一个 Easy

203 删除所有值为val的节点

【题目】

在这里插入图片描述
在这里插入图片描述

【分析】

在这里插入图片描述
cur用来遍历链表。
当cur值不为val时,p.next = cur, p = p.next;

【代码】

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) { //head是第一个节点。head.val是第一个节点的值。
        if(head == null) return head;

        ListNode Head = new ListNode(-1);   //虚拟头节点Head
        ListNode p = Head;

        ListNode cur = head;                //用于遍历链表
        while(cur!=null){
            if(cur.val != val){
                p.next = cur;
                p = p.next;
            }
            cur = cur.next;
        }
        p.next = null;
        return Head.next;
    }
}

结果:
在这里插入图片描述

m18 删除链表中值为val的节点,链表元素不重复

【题目】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

【分析】

链表元素不重复,所以只要找到它的前一个节点就大功告成了。
特殊情况就是要找的节点是第一个节点的情况。

【代码】

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteNode(ListNode head, int val) {
        if(head.val == val) return head.next;  //特殊情况,当删除的是第一个节点时

        ListNode p=head;
        while(p.next !=null){
            if(p.next.val == val){    //找到之后,删除即可
                p.next = p.next.next;
                break;
            }
            p = p.next;
        }
        return head;
    }
}

结果:
在这里插入图片描述

83 删除排序链表中的重复元素,重复只保留一个

【题目】

在这里插入图片描述
在这里插入图片描述

【分析】

尾插法重新建立一个链表。
用p遍历链表。当p.val != tail.val时,把p插入到新链表中。

【代码】

/**
 * 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 tail = head;       //新链表,尾指针
        ListNode p=head.next;       //用来遍历链表
        while(p!=null){
            if(p.val != tail.val){
                tail.next = p;
                tail=p;
            }
            p=p.next;
        }
        tail.next=null;
        return head;
    }
}

结果:
在这里插入图片描述

82 删除排序链表中的重复元素,重复的都删掉

【题目】

在这里插入图片描述
在这里插入图片描述

【方法一】

对于每一个节点,什么是不重复?
对于非尾节点: p的值不等于前一个节点的值 && p的值不等于后一个节点的值
对于尾节点: p的值不等于前一个节点的值

即:
(p!=p.front.val && p==null) || (p!=p.front.val && p!=p.next.val )

合起来为:
p !=p.front.val && (p==null || p!=p.next.val)

怎么知道前面节点的值呢?用一个变量front记录下来。front初始化为head.val-1,这样就肯定不影响head的重复性了。

/**
 * 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 || head.next==null) return head;

        ListNode Head = new ListNode(-1);
        ListNode tail = Head;
        ListNode p = head;                   //p遍历链表

        int front=head.val-1;               //front用来记录p的前一个节点的值
        while(p!=null){
            if(p.val != front && (p.next==null || p.val != p.next.val)){   //p不重复
                tail.next = p;
                tail = p;
            }
            front = p.val;                  //记录p的值
            p = p.next;
        }
        
        tail.next = null;
        return Head.next;
    }
}

结果:
在这里插入图片描述

【方法二】

比如,1->2->2->…->2->3->3->…->3->4->5
使用p遍历链表。
(1)一旦发现p.val = p.next.val,说明它是一个重复的节点。
在这里插入图片描述
接下来就把所有的2都跳过去。
int tmp = p.val;
while( p!=null && p.val==tmp){
p = p.next;
}
在这里插入图片描述
(2)如果p.val !=p.next.val,说明不重复。加到新链表中。

代码:

/**
 * 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 || head.next==null) return head;

        ListNode Head = new ListNode(-1);
        ListNode tail = Head;

        ListNode p = head;
        while(p!=null){       //遍历前n-1个节点
            if(p.next!=null && p.val == p.next.val){ //发现了重复的元素,就把重复的都跳过去
                int tmp = p.val;
                while(p!=null && p.val == tmp){
                    p= p.next;
                }
            }else{                   //元素唯一,就加到新链表中
                tail.next = p;
                tail = p;
                p = p.next;
            }
        }

        tail.next = null;
        return Head.next;
    }
}

结果:
在这里插入图片描述

m2 删除排序链表中的重复元素,重复只保留一个

【题目】

在这里插入图片描述

【分析】

搞一个数组记录一下,有没有出现过就好了。

【代码】

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeDuplicateNodes(ListNode head) {
        if(head==null) return null;

        int[] flag = new int[20001];      //记录val是否出现过

        ListNode Head = new ListNode(-1);
        ListNode tail=Head;

        ListNode p = head;
        while(p != null){  
            if(flag[p.val]==0){  //若之前没出现过
                flag[p.val]=1;
                tail.next = p;
                tail = p;
            }
            p = p.next;
        }
        tail.next = null;
        return Head.next;
    }
}

结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值