All O`one Data Structure

见到O(1),肯定是用哈希表了

但是取最大最小值的过程不是O(1),所以最好是在插入的过程中就能保持顺序

方法是维护一个矩阵,行是键的值,列是键(string)

(first)row0: val = 4, strs = {"A", "B"}
row1: val = 3, strs = {"D"}
(last)row2: val = 2, strs = {"C"}
inc过程:

if the key isn't in the matrix:
    if the matrix is empty or the value of the last row isn't 1:
        insert a new row with value 1 to the end of the matrix, and put the key in the new row;
    else:
        put the key in the last row of the matrix;
else:
    if the key is at the first row or last_row.value != current_row.value + 1:
        insert a new row before current row, with value current_row.value + 1, and move the key to the new row;
    else:
        move the key from current row to last row;

代码:

struct Bucket { int val; unordered_set<string> keys; };

list<Bucket> buckets;

unordered_map<string, list<Bucket>::iterator> m;

这三行定义完全定义了行号和键值(string)的映射关系,其中Bucket中的unordered_set进一步把查询的时间复杂度降到了O(1)

class AllOne {
public:
	/** Initialize your data structure here. */
	AllOne() {}

	/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
	void inc(string key) {
		if (!m.count(key)) {
			if (buckets.empty() || buckets.back().val != 1) {
				auto newBucket = buckets.insert(buckets.end(), { 1,{ key } });
				m[key] = newBucket;
			}
			else {
				auto newBucket = --buckets.end();
				newBucket->keys.insert(key);
				m[key] = newBucket;
			}
		}
		else {
			auto curBucket = m[key], lastBucket = (--m[key]);
			if (lastBucket == buckets.end() || lastBucket->val != curBucket->val + 1) {
				auto newBucket = buckets.insert(curBucket, { curBucket->val + 1,{ key } });
				m[key] = newBucket;
			}
			else {
				lastBucket->keys.insert(key);
				m[key] = lastBucket;
			}
			curBucket->keys.erase(key);
			if (curBucket->keys.empty()) buckets.erase(curBucket);
		}
	}

	/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
	void dec(string key) {
		if (!m.count(key)) return;
		auto curBucket = m[key];
		if (curBucket->val == 1) {
			curBucket->keys.erase(key);
			if (curBucket->keys.empty()) buckets.erase(curBucket);
			m.erase(key);
			return;
		}
		auto nextBucket = ++m[key];
		if (nextBucket == buckets.end() || nextBucket->val != curBucket->val - 1) {
			auto newBucket = buckets.insert(nextBucket, { curBucket->val - 1,{ key } });
			m[key] = newBucket;
		}
		else {
			nextBucket->keys.insert(key);
			m[key] = nextBucket;
		}
		curBucket->keys.erase(key);
		if (curBucket->keys.empty()) buckets.erase(curBucket);
	}

	/** Returns one of the keys with maximal value. */
	string getMaxKey() {
		return buckets.empty() ? "" : *(buckets.begin()->keys.begin());
	}

	/** Returns one of the keys with Minimal value. */
	string getMinKey() {
		return buckets.empty() ? "" : *(buckets.rbegin()->keys.begin());
	}
private:
	struct Bucket { int val; unordered_set<string> keys; };
	list<Bucket> buckets;
	unordered_map<string, list<Bucket>::iterator> m;
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值