LintCode 960: First Unique Number in Data Stream II (doubly linkedlist好题)

960 · First Unique Number in Data Stream II
Algorithms
Medium

Description
We need to implement a data structure named DataStream. There are two methods required to be implemented:

void add(number) // add a new number
int firstUnique() // return first unique number

You can assume that there must be at least one unique number in the stream when calling the firstUnique.

Example
Example 1:

Input:
add(1)
add(2)
firstUnique()
add(1)
firstUnique()
Output:
[1,2]
Example 2:

Input:
add(1)
add(2)
add(3)
add(4)
add(5)
firstUnique()
add(1)
firstUnique()
add(2)
firstUnique()
add(3)
firstUnique()
add(4)
firstUnique()
add(5)
add(6)
firstUnique()
Output:
[1,2,3,4,5,6]
Tags
Related Problems

209
First Unique Character in a String
Easy

646
First Position Unique Character
Easy

685
First Unique Number in Data Stream
Medium

解法1:
我的做法是基于doubly linked list,同时维护两个map,一个是<num, freq>,一个是<num, Node *>。注意doubley linked list有一个dummyHead, 一个dummyTail。每次都插到head的位置,这样只需要返回dummyTail前面一个元素的值就可以了。注意每次add num的时候,如果发现freq[num]>1了,需要把num对应的Node 节点删除。每次操作应该都是O(1)。

struct Node {
    int val;
    Node *prev, *next;
    Node(int v) : val(v), prev(NULL), next(NULL) {}
};

class DataStream {
public:
    DataStream(){
        dummyHead = new Node(0);
        dummyTail = new Node(0);
        dummyHead->next = dummyTail;
        dummyTail->prev = dummyHead;
    }
    
    /**
     * @param num: next number in stream
     * @return: nothing
     */
    void add(int num) {
        freq[num]++;
        //delete repeat node from doubly linked list
        if (freq[num] > 1 && mp.find(num) != mp.end()) {
            Node *deleteNode = mp[num];
            deleteNode->prev->next = deleteNode->next;
            deleteNode->next->prev = deleteNode->prev;
            delete(deleteNode);
            deleteNode = nullptr;
            mp.erase(num);
        }
        //always add to head
        if (freq[num] == 1) {
            Node *node = new Node(num);
            node->next = dummyHead->next;
            if (dummyHead->next) dummyHead->next->prev = node;
            node->prev = dummyHead;
            dummyHead->next = node;
            mp[num] = node;
        }
    }

    /**
     * @return: the first unique number in stream
     */
    int firstUnique() {
        //if (dummyHead->next == dummyTail) return -1; //但题目保证有至少一个unique,所以这行不需要
        return dummyTail->prev->val;
    }
private:
    unordered_map<int, Node *> mp;
    unordered_map<int, int> freq; //<int, freq>
    Node *dummyHead, *dummyTail;
};

解法2:用queue和unordered_map。
注意: 虽然firstUnique()里面有while(),其均摊时间复杂度仍然是O(1)。

class DataStream {
public:
    DataStream(){
    }
    
    /**
     * @param num: next number in stream
     * @return: nothing
     */
    void add(int num) {
        q.push(num);
        freq[num]++;
    }

    /**
     * @return: the first unique number in stream
     */
    int firstUnique() {
        while(!q.empty() && freq[q.front()] > 1) {
            q.pop();
        }
        if (q.empty()) return -1;
        return q.front();
    }
private:
    queue<int> q;
    unordered_map<int, int> freq; //<int, freq>
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值