本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
今天题目不要看很长,但是只要看懂题目的意思,并不是特别的难,主要是难在理解题目的意思。
每日一题
今天的每日一题为2034. 股票价格波动,难度为中等
-
给你一支股票价格的数据流。数据流中每一条记录包含一个 时间戳 和该时间点股票对应的 价格 。
-
不巧的是,由于股票市场内在的波动性,股票价格记录可能不是按时间顺序到来的。某些情况下,有的记录可能是错的。如果两个有相同时间戳的记录出现在数据流中,前一条记录视为错误记录,后出现的记录 更正 前一条错误的记录。
-
请你设计一个算法,实现:
-
更新 股票在某一时间戳的股票价格,如果有之前同一时间戳的价格,这一操作将 更正 之前的错误价格。
-
找到当前记录里 最新股票价格 。最新股票价格 定义为时间戳最晚的股票价格。
-
找到当前记录里股票的 最高价格 。
-
找到当前记录里股票的 最低价格 。
-
请你实现
StockPrice类: -
StockPrice()初始化对象,当前无股票价格记录。 -
void update(int timestamp, int price)在时间点timestamp更新股票价格为price。 -
int current()返回股票 最新价格 。 -
int maximum()返回股票 最高价格 。 -
int minimum()返回股票 最低价格 。
示例 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 。
提示:
- 1 <= timestamp, price <= 109
- update,current,maximum 和 minimum 总 调用次数不超过 105 。
- current,maximum 和 minimum 被调用时,update 操作 至少 已经被调用过 一次 。
题解
这道题是我最近看过的题目最长的题目了,但是不要被题目的长度吓到了,仔细一看会发现其实他他要求的方法都很简单:
StockPrice() 初始化对象
结合示例的第一条:
StockPrice stockPrice = new StockPrice();
这样我们不难发现,我们可以用一个类来做这道题,这里就要注意不要局限于系统给你初始化的那几个函数,在之前为了方便写几个工具方法都是很常见的,这次我们直接全部推倒,我们不用系统提供的方法,而是自己实现一个StockPrice 类:
class StockPrice {
constructor() {
}
}
void update(int timestamp, int price)
这个函数的作用是 在时间点 timestamp 更新股票价格为 price 。并且结合示例:
stockPrice.update(1, 10); // 时间戳为 [1] ,对应的股票价格为 [10] 。
stockPrice.update(2, 5); // 时间戳为 [1,2] ,对应的股票价格为 [10,5] 。
我们就更加能肯定我们用类来做这道题肯定是更方便的,因为实例也是直接调用stockPrice这个实例上面的方法,这样我们就可以直接将update方法挂在类里面。
然后根据题目描述的这个方法的作用,传入一个当前的时间戳和价格,去更新内存中响应的时间戳的价格,这里我们可以用一个map表来保存我们的时间戳和对于的价格。这样我们的类中就需要新增加一个
this.timePrice = new Map();
然后update就是判断这个表中是否有这项数据,有的话就更新,没有的话就加进去。
最新价格 最高价格 最低价格
关于最新价格,那么我们就需要去额外维护一个时间:
this.time = 0;
每次update的时候就要去判断时间是否变大,变大了就更新这个值。
然后就是最高价格和最低价格,这两个都相对简单,因为我们已经用一个map表来维护我们的数据了,最高和最低价格无非就是遍历这个map表然后输出对应的最高价格和最低价格就可以了。
本来一开始想着我维护一个最大值不就好了,但是后来发现,因为数据是会因为后面的updata改变的,所以一旦维护的最大值被修改,那就没办法判断此刻的最大值是什么了,所以干脆直接遍历map表。
总结
经过上面的这些分析,就会发现这道题其实特别简单,不过就是一个哈希表的事。所以主要是碰到长度过长的题目,也不用太过惊慌而直接cv,有时候可能会从示例的输入说明中发现这道题其实没有想象的那么难。
class StockPrice {
constructor() {
this.time = 0;
this.price = 0;
this.priceMap = new Map();
}
/*
* @param {number} timestamp
* @param {number} price
* @return {void}
*/
update(timestamp, price) {
this.priceMap.set(timestamp, price);
if (this.time <= timestamp) {
this.time = timestamp;
this.price = price;
}
}
/*
* @return {number}
*/
current() {
return this.price;
}
/*
* @return {number}
*/
maximum() {
let max = 0;
for (const price of this.priceMap.values()) {
if (max < price) max = price;
}
return max;
}
/*
* @return {number}
*/
minimum() {
let min = Infinity;
for (const price of this.priceMap.values()) {
if (min > price) min = price;
}
return min;
}
}