Leetcode 1019: Finding the next greatest node — the Domino effect
By: Abrar Shariar
Tags: Leetcode, Algorithms, Singly Linked List, Python3, Leetcode Medium

Hack it yourself!

The Problem and example I/O:

The problem statement is to find the next greatest element in a linked List. So for the ith node we have to find the jth node, such that node value of j is greater than ith.

The catch here is that we have to find the most recent one. Let’s take an example:

[2,1,5]

output => [5,5,0]

notice that for i=0, the greatest element after 2 is 5

for i = 1, next greatest = 5

for i = 2, does not have any next greatest, hence the zero 0

Another example,

[1,7,5,1,9,2,5,1]

output => [7,9,9,9,0,5,0,0]

running it by the previous explanation, it is apparent that reasoning behind the output

The Intuition

The idea is to think of it as a domino.

for the input:

[2,7,4,3,5]

let’s visualize how it would look like in a dominos:

domino for [2,7,4,5]

Now, think each of them as tiles. Which ones can drop as we go from left to right?

The intuition is —

list[i] = current element

list[i + 1] = the adjacent element on the right

if list[i+1] > list[i] then it will drop the list[i]

but there’s a gotcha:

look at the last 3 elements: 4,3,5

what happens when we reach 5?

clearly, 5 > 3

so it will kick down 3, but it won’t stop there, since 5> 4 (the next element after 3)

so, it will kick down 4 this time

notice that, we basically start a chain reaction every time we hit the condition of:

list[i+1] > list[i]

so, I have bolded the “chain reaction”, cause that would be critical to how we devise our algo and the data structures we use so handle this chain reaction.

The Simulation

For simulating, let’s consider a sample input:

[10,6,4,5,10,12]

Now, the correct output would look like:

[12, 10, 5, 10, 12, 0]

Let’s simulate the solution!

The data structures:

# the input list

input_list = [10,6,4,5,10,12] # stack to maintain the indices

stack = [] # output list

output_list = []

At first, we want to initialize the output_list with 0, so that we have a constant time i.e O(1) access to each indices

# after initializing with all 0s

output_list = [0,0,0,0,0,0]

The algorithm:

Loop over each element of the input_list On each iteration: check if the stack is non-empty If stack is empty => push(current element index) If stack not empty => keep poping the indices from the stack while it's non-empty AND the element on the top of the stack is less than the current element

Notice, that we are pushing the indices in the stack, the reason is the following:

Whenever we find the next largest node, we pop() the index from the top of the stack and update the output_list, in constant time!!

isn’t that cool?

Now, let’s run the algorithm:

# looping over each item of input_list i = 0:

el = input_list[i] = 10

# stack empty,push index i

stack = [0] i = 1

el = input_list[i] = 6

# 6 < 10 (top most item from stack), push index i

stack = [0,1] i = 2

el = input_list[i] = 4

# 4 < 6, push index i

stack = [0,1,2] i = 3

el = input_list[i] = 5

# 5 > 4, lets start poping! pop_index = 2

stack = [0,1] # input_list[pop_index] < el

output_list[pop_index] = el

output_list = [0,0,5,0,0,0] # element at top of stack (6) > el: we stop poping, push i

stack = [0,1,3]

i = 4

el = input_list[i] = 10

# 10 > 5, start popping! pop_index = stack.pop() = 3

output_list[pop_index] = el = 10

output_list = [0,0,5,10,0,0] pop_index = 1

output_list[pop_index] = el = 10

output_list = [0,10,5,10,0,0] pop_index = 10

output_list[pop_index] = el = 10

# since they are equal we move on i = 5

el = 12

12 > stack_top_item = 10

# WE POP pop_item_index = 0

output_list[pop_index] = el = 12

output_list = [12,10,5,10,12,0]

The Code