leetcode1661移除重复节点(移除未排序链表中的重复节点,保留最开始出现的节点)

编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。

示例1:
输入:[1, 2, 3, 3, 2, 1]
输出:[1, 2, 3]

示例2:
输入:[1, 1, 1, 1, 2]
输出:[1, 2]

提示:
链表长度在[0, 20000]范围内。
链表元素在[0, 20000]范围内。

进阶:
如果不得使用临时缓冲区,该怎么解决?
 

思路:我们最容易想到的就是用集合去重,从链表的头开始遍历,如果在HashSet集合中有出现重复的元素,我们直接过滤(删除)掉,时间复杂度为O(N)。

 

链表节点定义

public class ListNode {
    //节点存储的数据
    int val;
    
    //节点的后继节点
    ListNode next;

    //构造方法,生成一个节点时要存入一个数据
    public ListNode(int val) {
        this.val = val;
    }
}

 

方法实现与主方法测试

import java.util.HashSet;
import java.util.Set;

class Solution {
    public ListNode removeDuplicateNodes(ListNode head) {
        //pre指向当前节点的前驱
        ListNode pre = null;
        ListNode p = head;
        Set set = new HashSet<>();

        //遍历节点
        while (p != null) {
            //如果哈希表中已存在这个元素则删除
            if (set.contains(p.val)) {
                //删除,删除后前驱节点不需要往后移
                pre.next = p.next;
            } else {
                //如果哈希表中不存在这个元素则添加进来
                set.add(p.val);
                //未删除,前驱节点后移
                pre = p;
            }
            //无论是否删除都让p指向下一个待检测的节点
            p = p.next;
        }
        return head;
    }

    public static void main(String[] args) {
        //定义一个测试样例
        int arr[] = {1, 2, 3, 3, 2, 1};

        //将数组元素依次存入链表
        ListNode head = new ListNode(1);
        int i = 1;
        ListNode p1 = head;
        while (i < arr.length) {
            p1.next = new ListNode(arr[i]);
            p1 = p1.next;
            ++i;
        }

        //调用方法测试
        new Solution().removeDuplicateNodes(head);

        //输出样例的预期结果
        ListNode p2 = head;
        while (p2 != null) {
            System.out.print(p2.val + (p2.next == null ? "" : " "));
            p2 = p2.next;
        }
    }
}

 

对于进阶问题:如果不得使用临时缓冲区,该怎么解决?一种简单的方法是,我们在给定的链表上使用两重循环,其中第一重循环从链表的头节点开始,枚举一个保留的节点,这是因为我们保留的是「最开始出现的节点」。第二重循环从枚举的保留节点开始,到链表的末尾结束,将所有与保留节点相同的节点全部移除,时间复杂度为O(N^2)。

 

方法实现

public ListNode removeDuplicateNodes(ListNode head) {
//first节点指向每一轮比较的第一个节点
        ListNode first = head;
        while (first != null) {
            //scanner节点为每一轮第一个节点之后的节点
            //并依次与first节点比较,如果元素值相同则过滤掉
            ListNode scanner = first.next;
            //scanner节点的前驱节点
            ListNode pre = first;
            while (scanner != null) {
                if (first.val == scanner.val) {
                    pre.next = scanner.next;
                } else {
                    pre = scanner;
                }
                //让scanner指向下一个节点并与first节点比较
                scanner = scanner.next;
            }
            //依次选取下一个节点作为第一个节点
            first = first.next;
        }
        return head;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值