Idea
Why Mono Decreasing stack gives you next greater element
- As you scan the array, you keep the stack decreasing. ie the Top is lesser than item below it
- When a new number is larger than the top, the top gets popped.
- That pop event tells you: this new number is the next greater element for the popped one because nothing between them was greater.
Why Mono Increasing stack gives you next smaller element
- As you scan the array, you keep the stack increasing. ie the Top is greater than item below it
- When a new number is smaller than the top, the top gets popped.
- That pop event tells you: this new number is the next smaller element for the popped one because nothing between them was smaller.
Problems
Final Prices
type IndexValue struct {
Index int
Value int
}
func finalPrices(prices []int) []int {
mi := []IndexValue{}
for idx, price := range prices {
for len(mi) > 0 && mi[len(mi) - 1].Value >= price {
top := mi[len(mi) - 1]
prices[top.Index] = top.Value - price // use the top
mi = mi[:len(mi) - 1] // pop
}
mi = append(mi, IndexValue{
Value: price,
Index: idx,
})
}
return prices
}Next Greater Element
type MDStack struct {
Index int
Value int
}
func nextGreaterElement(nums1 []int, nums2 []int) []int {
Map := make(map[int]int)
st := []MDStack{}
for idx, val := range nums2 {
for len(st) > 0 && st[len(st) - 1].Value < val {
top := st[len(st) - 1]
st = st[:len(st) - 1]
Map[top.Value] = val
}
st = append(st, MDStack{
Index: idx,
Value: val,
})
}
ans := []int{}
for _, num := range nums1 {
v, ok := Map[num]
if !ok {
ans = append(ans, -1)
} else {
ans = append(ans, v)
}
}
return ans
}Next Greater Element 2
Its required to find the next greater element of a cyclic array. Simply running the mono decreasing strategy on the array does the trick
type IndexValue struct {
Index int
Value int
}
func nextGreaterElements(nums []int) []int {
ans := make([]int, len(nums))
for i := range ans {
ans[i] = -1
}
st:=[]IndexValue{}
for times := 0; times < 2; times++ {
for i, val := range nums {
for len(st) > 0 && st[len(st)-1].Value < val {
top := st[len(st)-1]
st = st[:len(st)-1]
if top.Index != i {
ans[top.Index] = val
}
}
st = append(st, IndexValue{
Index: i,
Value: val,
})
}
}
return ans
}Online Stock Span
The intuition is you apply the monotonic increasing array scan on a array without popping elements off, so that every time next is being called it would get its span. The solution turned out to be a O(n^2), since we are potentially looking back the whole price history
type StockSpanner struct {
priceHistory []int
}
func Constructor() StockSpanner {
return StockSpanner{
}
}
func (this *StockSpanner) Next(price int) int {
// As long as the current day disturbs the monotonic increasing property, we increase the count, and NOT pop the elements, so that next days calculation doesn't require to rebuild the stack
days := len(this.priceHistory)
span := 1
for days > 0 && price >= this.priceHistory[days - 1] {
span++
days--
}
this.priceHistory = append(this.priceHistory, price)
return span
}
/**
* Your StockSpanner object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Next(price);
*/