The task is taken from leetcode
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
push(x) -- Push element x onto stack.
pop() -- Removes the element on top of the stack.
top() -- Get the top element.
getMin() -- Retrieve the minimum element in the stack.
Example:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> Returns -3.
minStack.pop();
minStack.top(); --> Returns 0.
minStack.getMin(); --> Returns -2.
My first solution
/**
* initialize your data structure here.
*/
var MinStack = function() {
this.repo = [];
};
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function(x) {
if (!isNaN(x)) {
this.repo.push(x);
}
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
return this.repo.pop();
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {
return this.repo[this.repo.length - 1];
};
/**
* @return {number}
*/
MinStack.prototype.getMin = function() {
if (this.repo) {
const copy = this.repo.slice(0);
return copy.sort((a,b) => a - b)[0];
}
};
My second solution
/**
* initialize your data structure here.
*/
var MinStack = function() {
this.repo = [];
this.minRepo = [];
};
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function(x) {
if (!isNaN(x)) {
if (!this.minRepo.length || x <= this.minRepo[0]) {
this.minRepo.unshift(x);
}
this.repo.push(x);
}
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
if (this.repo.pop() === this.minRepo[0]) {
this.minRepo.shift();
}
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {
return this.repo[this.repo.length - 1];
};
/**
* @return {number}
*/
MinStack.prototype.getMin = function() {
if (this.minRepo.length) {
return this.minRepo[0];
}
};
For the second solution I was thinking of adding the numbers not from the back (with push
) but instead from the front (with unshift
). The advantage is that I would need less operation inside the method top (return this.repo[0]
would be sufficient - no need for calculating the last element with this.repo.length - 1
). But I don't whether this would be "weird" and would mean too much "mental mapping" (the function is called push
but I use a shift
inside).
2 Answers 2
Inconsistent style
The getMin
function checks if the stack is empty, and the top
function doesn't.
This inconsistency is confusing.
I'm not sure which way is better, but it's good to be consistent.
Unnecessary and over-eager input validation
push
checks if the parameter is a number, and quietly does nothing if it isn't.
If non-numbers should not be allowed, then it would be better to throw an exception than quietly ignore.
In any case, this check is not required by the exercise.
Naming
Instead of repo
, it would be more natural to call it stack
.
With the push
and pop
methods of JavaScript arrays,
the illusion is perfect.
Building from common building blocks
The second solution builds a secondary storage with the minimum values, and makes some effort to avoid duplicates. I'm not sure the extra effort is worth the added complexity. It would be simpler to not try to avoid duplicates, and simply add the pair of current and minimum values on every push. Then, it becomes easy to see that an implementation is possible without reimplementing a stack: under the hood you can use a stack, and the public methods simply encapsulate the transformations necessary for the underlying storage of value pairs.
var MinStack = function() {
this.stack = [];
};
MinStack.prototype.push = function(x) {
const min = this.stack.length ? Math.min(this.getMin(), x) : x;
this.stack.push([x, min]);
};
MinStack.prototype.pop = function() {
this.stack.pop()[0];
};
MinStack.prototype.top = function() {
return this.stack[this.stack.length - 1][0];
};
MinStack.prototype.getMin = function() {
return this.stack[this.stack.length - 1][1];
};
-
\$\begingroup\$ Your solution requires more space, doesn't it? \$\endgroup\$thadeuszlay– thadeuszlay2019年05月18日 06:26:21 +00:00Commented May 18, 2019 at 6:26
-
\$\begingroup\$ @thadeuszlay it's on the same order of space complexity as yours (\$O(n)\$), but yes, on average it will use more space. \$\endgroup\$janos– janos2019年05月18日 08:24:01 +00:00Commented May 18, 2019 at 8:24
The getMin
function is not constant. You need to keep track of the minimum value whenever you push or pop.
Furthermore you should name your functions.
-
\$\begingroup\$ In the first solution you mean? \$\endgroup\$thadeuszlay– thadeuszlay2019年05月17日 18:30:17 +00:00Commented May 17, 2019 at 18:30
-
\$\begingroup\$ In the second solution I keep track of the minimum value with every push and pop. \$\endgroup\$thadeuszlay– thadeuszlay2019年05月17日 19:08:03 +00:00Commented May 17, 2019 at 19:08
-
\$\begingroup\$ Yes, I meant in the first anser. \$\endgroup\$konijn– konijn2019年05月17日 23:40:14 +00:00Commented May 17, 2019 at 23:40
Explore related questions
See similar questions with these tags.