数据流中第一个独特的数 II (lint960)——哈希

数据流中第一个独特的数 II

描述

我们需要实现一个叫 DataStream 的数据结构。并且这里有两个方法需要实现:

  1. void add(number) // 加一个新的数
  2. int firstUnique() // 返回第一个独特的数

你可以假设在调用 firstUnique 方法时,数据流中至少有一个独特的数字

样例

输入:
add(1)
add(2)
firstUnique()
add(1)
firstUnique()
输出:
[1,2]

题解1:HashMap + List

HashMap:存储数字出现的次数

List: 顺序存储添加的数字

class DataStream {
    private HashMap<Integer, Integer> map;
    private List<Integer> list;

    public DataStream() {
        list = new ArrayList<>();
        map = new HashMap<>();
    }

    public void add(int num) {
        list.add(num);
        map.put(num, map.getOrDefault(num, 0) + 1);
    }

    public int firstUnique() {
        for (Integer num : list) {
            if (map.get(num) == 1) {
                return num;
            }
        }
        return -1;
    }
}

题解2:Queue + Set

Queue: 按添加顺序保存只出现一次的数

Set: 数据流中已有的数

image-20220525150156553
class DataStream {
    private Queue<Integer> queue;
    private Set<Integer> set;

    public DataStream() {
        queue = new ArrayDeque<>();
        set = new HashSet<>();
    }

    public void add(int num) {
        if(set.contains(num)) {
            queue.remove(num);
            return;
        }

        set.add(num);
        queue.add(num);
    }

    public int firstUnique() {
        if(queue.size() == 0) {
            return -1;
        }
        return queue.peek();
    }
}

题解3: ListNode链表 + HashMap+ Set

ListNode链表:按添加顺序存储只出现一次的数

HashMap<Integer, ListNode>:保存数的前节点

Set: 保存出现2次以上的数

image-20220525150156553
class DataStream {
    private ListNode dummy; //哨兵节点
    private ListNode tail;  //尾结点
    private Map<Integer, ListNode> pres;
    private Set<Integer> set;

    public DataStream() {
        dummy = new ListNode(0);
        tail = dummy;

        pres = new HashMap<>();
        set = new HashSet<>();
    }
    
    public int firstUnique() {
        if(dummy.next == null) {
            return -1;
        }
        return dummy.next.val;
    }
    
    public void add(int num) {
        if(set.contains(num)) return;

        if(pres.containsKey(num)) {
            remove(num);
            set.add(num);
        }else {
            ListNode node = new ListNode(num);
            pres.put(num, tail);
            tail.next = node;
            tail = node;
        }
    }

    public void remove(int num) {
        ListNode p = pres.get(num);
        p.next = p.next.next;

        pres.remove(num);

        if(p.next != null) {
            pres.put(p.next.val, p);
        }else {
            tail = p;
        }
    }

}

posted @ 2022-05-25 15:08  言思宁  阅读(25)  评论(0编辑  收藏  举报