【Lintcode】960. First Unique Number in Data Stream II

题目地址:

https://www.lintcode.com/problem/first-unique-number-in-data-stream-ii/description

要求实现一个数据结构,可以实现下面操作:
1、添加一个数字;
2、求按添加顺序来看,第一个只出现过一次的数字。

可以用哈希表 + 链表来做。哈希表key存数字,value存链表节点。我们开两个变量,一个dummy节点,还有一个tail节点,tail节点存链表的最后一个节点。该链表就存所有按添加顺序的且只出现过一次的数字。具体是这样做的。当添加一个数字的时候,先看哈希表的key里有没有,如果有了,那么这个数字再也不可能是唯一数字了,就将其从链表中删除,并将这个数字对应的value存为null,表示该数字永不考虑(如果添加的数字在哈希表里有key,但value是null,则直接返回就行);如果哈希表里没有,则说明该数字是唯一数字,添加到链表结尾。返回唯一数字,其实就是返回dummy.next的value。代码如下:

import java.util.HashMap;
import java.util.Map;

public class DataStream {
    
    class ListNode {
        int val;
        ListNode prev, next;
        
        public ListNode(int val) {
            this.val = val;
        }
    }
    
    private ListNode dummy, tail;
    private Map<Integer, ListNode> map;
    
    public DataStream() {
        // do intialization if necessary
        map = new HashMap<>();
        dummy = tail = new ListNode(0);
    }
    
    /**
     * @param num: next number in stream
     * @return: nothing
     */
    public void add(int num) {
        // write your code here
        if (map.containsKey(num)) {
        	// 如果哈希表里有num这个key,但value是null,
        	// 意味着这个num永远不会是唯一数字,直接return
            if (map.get(num) == null) {
                return;
            }
            
            // 否则说明num这个数字之前只出现过一次,这是第二次添加,则将第一次添加的那个节点删掉
            ListNode node = map.get(num);
            // 其value置为null
            map.put(num, null);
            node.prev.next = node.next;
            // 删除的时候要考虑node自己是不是tail,如果是,则要更新tail
            if (node.next != null) {
                node.next.prev = node.prev;
            } else {
                tail = node.prev;
            }
        } else {
        	// 如果哈希表里没有num这个key,说明num是第一次见,则加在链表结尾
        	tail.next = new ListNode(num);
	        tail.next.prev = tail;
    	    tail = tail.next;
        	map.put(num, tail);
        }
    }
    
    /**
     * @return: the first unique number in stream
     */
    public int firstUnique() {
        // write your code here
        return dummy.next.val;
    }
}

所有操作时间复杂度 O ( 1 ) O(1) O(1),空间复杂度取决于具体输入。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值