列表

详情


2034. 股票价格波动

给你一支股票价格的数据流。数据流中每一条记录包含一个 时间戳 和该时间点股票对应的 价格 。

不巧的是,由于股票市场内在的波动性,股票价格记录可能不是按时间顺序到来的。某些情况下,有的记录可能是错的。如果两个有相同时间戳的记录出现在数据流中,前一条记录视为错误记录,后出现的记录 更正 前一条错误的记录。

请你设计一个算法,实现:

请你实现 StockPrice 类:

 

示例 1:

输入:
["StockPrice", "update", "update", "current", "maximum", "update", "maximum", "update", "minimum"]
[[], [1, 10], [2, 5], [], [], [1, 3], [], [4, 2], []]
输出:
[null, null, null, 5, 10, null, 5, null, 2]

解释:
StockPrice stockPrice = new StockPrice();
stockPrice.update(1, 10); // 时间戳为 [1] ,对应的股票价格为 [10] 。
stockPrice.update(2, 5);  // 时间戳为 [1,2] ,对应的股票价格为 [10,5] 。
stockPrice.current();     // 返回 5 ,最新时间戳为 2 ,对应价格为 5 。
stockPrice.maximum();     // 返回 10 ,最高价格的时间戳为 1 ,价格为 10 。
stockPrice.update(1, 3);  // 之前时间戳为 1 的价格错误,价格更新为 3 。
                          // 时间戳为 [1,2] ,对应股票价格为 [3,5] 。
stockPrice.maximum();     // 返回 5 ,更正后最高价格为 5 。
stockPrice.update(4, 2);  // 时间戳为 [1,2,4] ,对应价格为 [3,5,2] 。
stockPrice.minimum();     // 返回 2 ,最低价格时间戳为 4 ,价格为 2 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class StockPrice { public: StockPrice() { } void update(int timestamp, int price) { } int current() { } int maximum() { } int minimum() { } }; /** * 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(); */

cpp 解法, 执行用时: 376 ms, 内存消耗: 158.9 MB, 提交时间: 2023-10-08 07:34:04

typedef pair<int,int> pii;

class StockPrice {
public:
    StockPrice() {
        this->maxTimestamp = 0;
    }
    
    void update(int timestamp, int price) {
        maxTimestamp = max(maxTimestamp, timestamp);
        timePriceMap[timestamp] = price;
        pqMax.emplace(price, timestamp);
        pqMin.emplace(price, timestamp);
    }
    
    int current() {
        return timePriceMap[maxTimestamp];
    }
    
    int maximum() {
        while (true) {
            int price = pqMax.top().first, timestamp = pqMax.top().second;
            if (timePriceMap[timestamp] == price) {
                return price;
            }
            pqMax.pop();
        }
    }
    
    int minimum() {
        while (true) {
            int price = pqMin.top().first, timestamp = pqMin.top().second;
            if (timePriceMap[timestamp] == price) {
                return price;
            }
            pqMin.pop();
        }
    }
private:
    int maxTimestamp;
    unordered_map<int, int> timePriceMap;
    priority_queue<pii, vector<pii>, less<pii>> pqMax;
    priority_queue<pii, vector<pii>, greater<pii>> pqMin;
};

/**
 * 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();
 */

cpp 解法, 执行用时: 420 ms, 内存消耗: 163.7 MB, 提交时间: 2023-10-08 07:33:41

class StockPrice {
public:
    StockPrice() {
        this->maxTimestamp = 0;
    }
    
    void update(int timestamp, int price) {
        maxTimestamp = max(maxTimestamp, timestamp);
        int prevPrice = timePriceMap.count(timestamp) ? timePriceMap[timestamp] : 0;
        timePriceMap[timestamp] = price;
        if (prevPrice > 0) {
            auto it = prices.find(prevPrice);
            if (it != prices.end()) {
                prices.erase(it);
            }
        }
        prices.emplace(price);
    }
    
    int current() {
        return timePriceMap[maxTimestamp];
    }
    
    int maximum() {
        return *prices.rbegin();
    }
    
    int minimum() {
        return *prices.begin();
    }
private:
    int maxTimestamp;
    unordered_map<int, int> timePriceMap;
    multiset<int> prices;
};

/**
 * 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();
 */

javascript 解法, 执行用时: 516 ms, 内存消耗: 87 MB, 提交时间: 2023-10-08 07:32:46

var StockPrice = function() {
    this.map = new Map();
    this.obj = {
        time: -1,
        price: -1
    };
    // 可以整体排序,避免每一次都需要排序
    this.maxQueue = new MaxPriorityQueue({
        compare: (e1,e2) => e2.price - e1.price
    });
    this.minQueue = new MinPriorityQueue({
        compare: (e1,e2) => e1.price - e2.price
    });
};

/** 
 * @param {number} timestamp 
 * @param {number} price
 * @return {void}
 */
StockPrice.prototype.update = function(timestamp, price) {
    this.map.set(timestamp, price);
    this.maxQueue.enqueue({
        time: timestamp,
        price: price
    });
    this.minQueue.enqueue({
        time: timestamp,
        price: price
    });
    if(this.obj.time <= timestamp) {
        this.obj.price = price
        this.obj.time = timestamp
    }
};

/**
 * @return {number}
 */
StockPrice.prototype.current = function() {
    return this.obj.price;
};

/**
 * @return {number}
 */
StockPrice.prototype.maximum = function() {
    // 判断当前的是否是正确的
    while(true) {
        let cur = this.maxQueue.front(), t = this.map.get(cur.time);
        if(cur.price === t) {
            return cur.price;
        }else this.maxQueue.dequeue();
    }
};

/**
 * @return {number}
 */
StockPrice.prototype.minimum = function() {
    while(true) {
        let cur = this.minQueue.front(), t = this.map.get(cur.time);
        if(cur.price === t) {
            return cur.price;
        }else this.minQueue.dequeue();
    }
};

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

rust 解法, 执行用时: 112 ms, 内存消耗: 41.6 MB, 提交时间: 2023-10-08 07:30:23

use std::collections::{BTreeMap, HashMap, HashSet};

struct StockPrice {
    time_tab: HashMap<i32, i32>,
    cur_time: i32,
    cur_price: i32,
    price_tab: BTreeMap<i32, HashSet<i32>>
}


/**
 * `&self` means the method takes an immutable reference.
 * If you need a mutable reference, change it to `&mut self` instead.
 */
impl StockPrice {

    fn new() -> Self {
        Self {
            time_tab: HashMap::with_capacity(10000),
            cur_time: 0,
            cur_price: 0,
            price_tab: BTreeMap::new(),
        }
    }
    
    fn update(&mut self, timestamp: i32, price: i32) {
        if timestamp >= self.cur_time {
            self.cur_time = timestamp;
            self.cur_price = price;
        }
        if let Some(p) = self.time_tab.get_mut(&timestamp) {
            let old_price = *p;
            *p = price;
            let t = self.price_tab.get_mut(&old_price).unwrap();
            t.remove(&timestamp);
            if t.is_empty() {
                self.price_tab.remove(&old_price);
            }
            let t = self.price_tab.entry(price).or_insert(HashSet::new());
            t.insert(timestamp);
        } else {
            self.time_tab.insert(timestamp, price);
            let t = self.price_tab.entry(price).or_insert(HashSet::new());
            t.insert(timestamp);
        }
    }
    
    fn current(&self) -> i32 {
        self.cur_price
    }

    fn maximum(&self) -> i32 {
        *self.price_tab.iter().rev().next().unwrap().0
    }
    
    fn minimum(&self) -> i32 {
        *self.price_tab.iter().next().unwrap().0
    }
}



/**
 * Your StockPrice object will be instantiated and called as such:
 * let obj = StockPrice::new();
 * obj.update(timestamp, price);
 * let ret_2: i32 = obj.current();
 * let ret_3: i32 = obj.maximum();
 * let ret_4: i32 = obj.minimum();
 */

python3 解法, 执行用时: 504 ms, 内存消耗: 64.3 MB, 提交时间: 2023-06-25 09:53:32

class StockPrice:
    def __init__(self):
        self.maxPrice = []
        self.minPrice = []
        self.timePriceMap = {}
        self.maxTimestamp = 0

    def update(self, timestamp: int, price: int) -> None:
        heappush(self.maxPrice, (-price, timestamp))
        heappush(self.minPrice, (price, timestamp))
        self.timePriceMap[timestamp] = price
        self.maxTimestamp = max(self.maxTimestamp, timestamp)

    def current(self) -> int:
        return self.timePriceMap[self.maxTimestamp]

    def maximum(self) -> int:
        while True:
            price, timestamp = self.maxPrice[0]
            if -price == self.timePriceMap[timestamp]:
                return -price
            heappop(self.maxPrice)

    def minimum(self) -> int:
        while True:
            price, timestamp = self.minPrice[0]
            if price == self.timePriceMap[timestamp]:
                return price
            heappop(self.minPrice)

# Your StockPrice object will be instantiated and called as such:
# obj = StockPrice()
# obj.update(timestamp,price)
# param_2 = obj.current()
# param_3 = obj.maximum()
# param_4 = obj.minimum()

golang 解法, 执行用时: 500 ms, 内存消耗: 41.2 MB, 提交时间: 2023-06-25 09:52:49

type StockPrice struct {
    prices       *redblacktree.Tree
    timePriceMap map[int]int
    maxTimestamp int
}

func Constructor() StockPrice {
    return StockPrice{redblacktree.NewWithIntComparator(), map[int]int{}, 0}
}

func (sp *StockPrice) Update(timestamp, price int) {
    if prevPrice := sp.timePriceMap[timestamp]; prevPrice > 0 {
        if times, _ := sp.prices.Get(prevPrice); times.(int) > 1 {
            sp.prices.Put(prevPrice, times.(int)-1)
        } else {
            sp.prices.Remove(prevPrice)
        }
    }
    times := 0
    if val, ok := sp.prices.Get(price); ok {
        times = val.(int)
    }
    sp.prices.Put(price, times+1)
    sp.timePriceMap[timestamp] = price
    if timestamp >= sp.maxTimestamp {
        sp.maxTimestamp = timestamp
    }
}

func (sp *StockPrice) Current() int { return sp.timePriceMap[sp.maxTimestamp] }
func (sp *StockPrice) Maximum() int { return sp.prices.Right().Key.(int) }
func (sp *StockPrice) Minimum() int { return sp.prices.Left().Key.(int) }


/**
 * Your StockPrice object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Update(timestamp,price);
 * param_2 := obj.Current();
 * param_3 := obj.Maximum();
 * param_4 := obj.Minimum();
 */

java 解法, 执行用时: 109 ms, 内存消耗: 102.5 MB, 提交时间: 2023-06-25 09:52:12

class StockPrice {
    private int maxTime;
    private Map<Integer, Integer> timeMap;
    private TreeMap<Integer, Integer> priceMap;
    public StockPrice() {
        maxTime = 0;
        timeMap = new HashMap<>();
        priceMap = new TreeMap<>();
    }
    
    public void update(int timestamp, int price) {
        if(timeMap.containsKey(timestamp)){
            int oldPrice = timeMap.get(timestamp);
            int cnt = priceMap.get(oldPrice);
            if(cnt == 1)
                priceMap.remove(oldPrice);
            else
                priceMap.put(oldPrice, cnt - 1);
        }
        timeMap.put(timestamp, price);
        priceMap.put(price, priceMap.getOrDefault(price, 0) + 1);
        maxTime = Math.max(maxTime, timestamp);
    }
    
    public int current() {
        return timeMap.get(maxTime);
    }
    
    public int maximum() {
        return priceMap.lastKey();
    }
    
    public int minimum() {
        return priceMap.firstKey();
    }
}

/**
 * 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();
 */

golang 解法, 执行用时: 488 ms, 内存消耗: 41.9 MB, 提交时间: 2023-06-25 09:51:48

type StockPrice struct {
    maxTime int
    timeMap map[int]int
    maxPrice, minPrice IntHeap
}


func Constructor() StockPrice {
    return StockPrice{timeMap:map[int]int{}}
}


func (this *StockPrice) Update(timestamp int, price int)  {
    if this.maxTime < timestamp {
        this.maxTime = timestamp
    }
    this.timeMap[timestamp] = price
    heap.Push(&this.maxPrice, []int{-price, timestamp})
    heap.Push(&this.minPrice, []int{price, timestamp})
}


func (this *StockPrice) Current() int {
    return this.timeMap[this.maxTime]
}


func (this *StockPrice) Maximum() int {
    for {
        cur := heap.Pop(&this.maxPrice).([]int)
        v := this.timeMap[cur[1]]
        if v == -cur[0] {
            heap.Push(&this.maxPrice, cur)
            return v
        }
    }
}


func (this *StockPrice) Minimum() int {
    for {
        cur := heap.Pop(&this.minPrice).([]int)
        v := this.timeMap[cur[1]]
        if v == cur[0] {
            heap.Push(&this.minPrice, cur)
            return v
        }
    }
}


/**
 * Your StockPrice object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Update(timestamp,price);
 * param_2 := obj.Current();
 * param_3 := obj.Maximum();
 * param_4 := obj.Minimum();
 */

type IntHeap [][]int
func (h IntHeap) Len() int{return len(h)}
func (h IntHeap) Less(i, j int) bool{return h[i][0] < h[j][0]}
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i]}
func (h *IntHeap) Pop() interface{} {
    old := *h
    n := len(old)
    x := old[n - 1]
    *h = old[0 : n - 1]
    return x
}
func (h *IntHeap) Push(x interface{}) {
    *h = append(*h, x.([]int))
}

python3 解法, 执行用时: 652 ms, 内存消耗: 55.7 MB, 提交时间: 2023-06-25 09:51:12

'''
模拟
维护一个最大的时间戳,维护一个价格的有序列表(在相同时间戳更新价格时删掉原来错误的时间戳)
'''
from sortedcontainers import SortedList
class StockPrice:
    def __init__(self):
        self.sl = SortedList()
        self.time_map = {}
        self.max_time = -inf

    def update(self, timestamp: int, price: int) -> None:
        if timestamp in self.time_map:
            self.sl.discard(self.time_map[timestamp])
        self.sl.add(price)
        self.time_map[timestamp] = price
        self.max_time = max(self.max_time, timestamp)

    def current(self) -> int:
        return self.time_map[self.max_time]

    def maximum(self) -> int:
        return self.sl[-1]

    def minimum(self) -> int:
        return self.sl[0]


# Your StockPrice object will be instantiated and called as such:
# obj = StockPrice()
# obj.update(timestamp,price)
# param_2 = obj.current()
# param_3 = obj.maximum()
# param_4 = obj.minimum()

上一题