This Interview question was asked in Atlassian's frontend interview. The problem statement reads as
Given a list of timestamps and commodity prices, find out highest commodity price at given timestamp. timestamps are not necessarily in sorted order, there can be multiple entries for a timestamp as well.
Followup
This question can be considered as DSA or JavaScript-based problem, ultimately we have to solve it and provide solution to it.
We will solve the question in two parts only as it is asked.
Reading the base problem statement, we know that we have to store a list of commodity prices for a given stamp and the prices can be in a random order. Thus we will create a hashMap and store the commodity prices in an array at the given timestamp. We will timestamp as the key.
const Store = function(){
this.store = new Map();
this.add = (timeStamp, price) => {
// check if timestamp is already present
// then push the new commodity price
if(this.store.has(timeStamp)){
const prices = this.store.get(timeStamp);
this.store.set(timeStamp, [price, ...prices]);
}
// create a new entry for the timestamp
else{
this.store.set(timeStamp, [price]);
}
};
}
To get the highest price, we will get all the commodity prices of the timestamp and return the highest among it.
this.highestPrice = (timeStamp) => {
const prices = this.store.get(timeStamp) ?? [];
return Math.max(...prices) ?? 0;
};
const Store = function(){
this.store = new Map();
this.add = (timeStamp, price) => {
// check if timestamp is already present
// then push the new commodity price
if(this.store.has(timeStamp)){
const prices = this.store.get(timeStamp);
this.store.set(timeStamp, [price, ...prices]);
}
// create a new entry for the timestamp
else{
this.store.set(timeStamp, [price]);
}
};
this.highestPrice = (timeStamp) => {
const prices = this.store.get(timeStamp) ?? [];
return Math.max(...prices) ?? 0;
};
};
Input:
const s = new Store();
s.add(1, 1);
s.add(1, 4);
s.add(1, 2);
console.log(s.highestPrice(1));
Output:
4
You can additional methods to get the lowest or the latest prices as well.
To get the commodity prices till a checkpoint, we will have to modify the function. We will have to accept the checkpoint (an unique identifier), I am using a random string differentiating from the number and store this checkpoint value in the commodity prices array only.
const Store = function(){
this.store = new Map();
this.add = (timeStamp, price, checkpoint) => {
// check if timestamp is already present
// then push the new commodity price
if(this.store.has(timeStamp)){
const prices = this.store.get(timeStamp);
this.store.set(timeStamp, [...prices, price]);
}
// create a new entry for the timestamp
else{
this.store.set(timeStamp, [price]);
}
// Mark the checkpoint after the last price entry
if(checkpoint){
const prices = this.store.get(timeStamp);
this.store.set(timeStamp, [...prices, checkpoint]);
}
};
}
Alternatively, you can store the checkpoint with the last price index in a separate hashMap, it is upto you how you define the logic. Now, while fetching the values, if no checkpoint is passed, then we filter out the checkpoints from the commodity prices array and return the highest among them. Else, if the checkpoint is passed, we return the max price till the index of the checkpoint in the array.
this.highestPrice = (timeStamp, checkpoint) => {
let prices = this.store.get(timeStamp) ?? [];
// If checkpoint is passed, get the list till the checkpoint
if(checkpoint){
let checkpointIndex = prices.findIndex((e) => e === checkpoint);
prices = prices.slice(0, checkpointIndex);
}
return this.getMax(prices);
};
this.getMax = (pricesList) => {
// filter non-numeric values (remove checkpoint marks)
const prices = pricesList.filter((e) => Number(e));
return Math.max(...prices) ?? 0;
}
const Store = function(){
this.store = new Map();
this.add = (timeStamp, price, checkpoint) => {
// check if timestamp is already present
// then push the new commodity price
if(this.store.has(timeStamp)){
const prices = this.store.get(timeStamp);
this.store.set(timeStamp, [...prices, price]);
}
// create a new entry for the timestamp
else{
this.store.set(timeStamp, [price]);
}
// Mark the checkpoint after the last price entry
if(checkpoint){
const prices = this.store.get(timeStamp);
this.store.set(timeStamp, [...prices, checkpoint]);
}
};
this.highestPrice = (timeStamp, checkpoint) => {
let prices = this.store.get(timeStamp) ?? [];
// If checkpoint is passed, get the list till the checkpoint
if(checkpoint){
let checkpointIndex = prices.findIndex((e) => e === checkpoint);
prices = prices.slice(0, checkpointIndex);
}
return this.getMax(prices);
};
this.getMax = (pricesList) => {
// filter non-numeric values (remove checkpoint marks)
const prices = pricesList.filter((e) => Number(e));
return Math.max(...prices) ?? 0;
}
};
Input:
const s = new Store();
s.add(1, 1);
s.add(1, 4);
s.add(1, 2);
s.add(1, 3, 'a');
s.add(1, 6);
s.add(1, 7);
s.add(1, 8, 'b');
Output:
console.log(s.highestPrice(1, 'a')); // 4
console.log(s.highestPrice(1, 'b')); // 8