【力扣每日一题】2034. 股票价格波动

考点

  • 哈希表
  • 红黑树

题意

设计一个算法,实现以下四个操作:

  • 更新:给定时间戳和对应的股票价格(不按照时间顺序排列),更新股票在某一时间戳的股票价格,如果有之前同一时间戳的价格,这一操作将更正之前的错误价格。
  • 找到当前记录里最新股票价格。最新股票价格定义为时间戳最晚的股票价格
  • 找到当前记录里股票的最高价格
  • 找到当前记录里股票的最低价格

思路

要得到最新股票价格很容易,只需要维护一个curPrice和curTimestamp,每当有新记录输入的时候,比较一下时间戳,如果timestamp>=curTimestamp,更新即可。

最高和最低价格的获取则相对复杂。原因在于更新记录可能导致原有的价格被替换,也就是说,在排序的同时还存在频繁的插入和删除操作。

这就不得不提到我们伟大的面试杀手红黑树了:

红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。
它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除(这里的n是树中元素的数目)。

c++里的map内部就是基于红黑树实现的,因此插入的时候会对键值进行自动排序。
与之相对的是unordered_map,内部用哈希表实现,不会根据key值大小进行排序。

map unordered_map
实现机理 红黑树 哈希表
内部元素有序性 有序 无序
运行效率 可以在O(log n)时间内做查找,插入和删除 存储和查找的时间复杂度可达到O(1)
内存占用 内存使用较少 以空间换时间,内存占用较高

简而言之,在需要有序性或者对单次查询有时间要求的应用场景下,应使用map,其余情况应使用unordered_map。
可参考:map与unordered_map的性能对比

回到题目中,这两种容器恰好都是我们需要的:
1.我们需要用到红黑树来记录价格,键值对为。count表示价格为price的时间戳的数量(如果数量为0,就从map中删除该节点)。map会在插入和删除键值对的过程中进行自动排序,我们直接从map的头部和尾部分别取得最小值和最大值即可。
2.还需要用哈希表记录某一时间戳的股票价格,键值对为。输入一条新记录时,如果时间戳已存在,需要通过哈希表查找之前的价格oldPrice,将红黑树上oldPrice对应的count减去1,再插入新的price。

代码

class StockPrice {
private:
	// 记录某一时间戳的股票价格的哈希表.键值对为
    unordered_map<int, int> hashMap;   
    // 记录某一价格及其对应的时间戳的数量的红黑树.键值对为(对key值从小到大进行自动排序)
    map<int, int> treeMap;         
    int curPrice;
    int curTimestamp;
public:
    StockPrice() {
        curTimestamp = 0;
    }
    
    void update(int timestamp, int price) {
        // 更新最新股票价格
        if (timestamp >= curTimestamp){
            curPrice = price;
            curTimestamp = timestamp;
        }
        // 更新红黑树
        if (hashMap.count(timestamp)){
            // 若时间戳已存在
            // 找到该时间戳原本对应的价格并移除
            int oldPrice = hashMap[timestamp];
            if(--treeMap[oldPrice] == 0)
                treeMap.erase(oldPrice);
        }
        hashMap[timestamp] = price;
        treeMap[price] += 1;
    }
    
    int current() {
        return curPrice;
    }
    
    int maximum() {
        return treeMap.rbegin() -> first;
    }
    
    int minimum() {
        return treeMap.begin() -> first;
    }
};

/**
 * Your StockPrice object will be instantiated and called as such:
 * StockPrice* obj = new StockPrice();
 * obj->update(timestamp,price);
 * int param_2 = obj->current();
 * int param_3 = obj->maximum();
 * int param_4 = obj->minimum();
 */

你可能感兴趣的:(leetcode题解,leetcode,数据结构)