Skip to content

Commit e108d6e

Browse files
committed
Added kth next greater element Python script.
1 parent 456d644 commit e108d6e

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""
2+
Author : Yuan Jack Yao
3+
Date : May 27, 2026
4+
5+
Implement the function to find the kth Next Greatest Element (NGE), if it exists, for all elements.
6+
"""
7+
8+
from __future__ import annotations
9+
10+
11+
test_k = 10
12+
test_array = [value for value in range(10000)]
13+
expected_answers = [value + test_k for value in range(10000 - test_k)] + [None] * test_k
14+
15+
16+
def find_kth_next_greater_element(
17+
array: list[int | float], k: int
18+
) -> list[int | float | None]:
19+
"""
20+
Efficient general method to seek the kth NGE for all elements.
21+
22+
Approach is entirely based on k stacks, which are actually very easy to understand.
23+
These k stacks symbolize how many NGEs an element has already found.
24+
25+
For example, for 1 <= j <= k, if an element is currently at the jth stack,
26+
it means that this element has found its (j - 1)th NGE, now looking for jth NGE.
27+
28+
By processing stacks from higher to lower ordinals, we can always ensure that
29+
each stack secures decreasing monotonicity in terms of element value.
30+
31+
Time complexity: O(kn) where n is the length of input array.
32+
However, if k >= n, all elements won't find their respective kth NGE.
33+
As a result, worst case time complexity is O(n^2) when k < n but k ≈ n.
34+
35+
Space complexity: O(n), since at any point, an element can only stay in one of these k stacks.
36+
37+
Args:
38+
array (list[int | float]): A list for which the kth NGE is computed.
39+
A mix of integers and floats in list is allowed.
40+
41+
k (int): Ordinal of the NGE to find. k must be a positive integer.
42+
43+
Returns:
44+
A list containing each element's kth NGE. If an element can't find its kth NGE,
45+
None, instead of -1, is put as its entry, because input array might have -1.
46+
47+
Example:
48+
>>> find_kth_next_greater_element([1, 2, 3, 4, 5, 6, 7], 3) == [4, 5, 6, 7, None, None, None]
49+
True
50+
>>> find_kth_next_greater_element([2.5, 1.9, 4.3, 3.5, 6.0, 5.8], 1) == [4.3, 4.3, 6.0, 6.0, None, None]
51+
True
52+
>>> find_kth_next_greater_element([value for value in range(1000)], 1000) == [None] * 1000
53+
True
54+
>>> find_kth_next_greater_element(test_array, test_k) == expected_answers
55+
True
56+
"""
57+
if not isinstance(k, int) or k < 1:
58+
raise ValueError("k must be a positive integer.")
59+
60+
kth_next_greater_elements: list[int | float | None] = [None] * len(array)
61+
if k >= len(array): # Trivial cases: nobody can have kth NGE.
62+
return kth_next_greater_elements
63+
64+
# For 1 <= j <= k, the jth stack is at the jth idx of stacks list.
65+
# stacks[0]: a transporter that transfer entries between stacks.
66+
# Each stack's entry is a tuple of (element, idx).
67+
stacks: list[list[tuple[int | float, int]]] = [[] for _ in range(k + 1)]
68+
69+
for idx, element in enumerate(array):
70+
# From kth stack to answer found.
71+
while stacks[k] and stacks[k][-1][0] < element:
72+
_, prev_idx = stacks[k].pop()
73+
kth_next_greater_elements[prev_idx] = element
74+
75+
for stack_ord in range(k - 1, 0, -1): # From (k - 1)th to 1st stack.
76+
while stacks[stack_ord] and stacks[stack_ord][-1][0] < element:
77+
stacks[0].append(stacks[stack_ord].pop())
78+
79+
while stacks[0]: # Move to the next ordered stack.
80+
stacks[stack_ord + 1].append(stacks[0].pop())
81+
82+
unvisited_elements_count = len(array) - 1 - idx
83+
if unvisited_elements_count >= k: # Element has a chance to find kth NGE.
84+
stacks[1].append((element, idx)) # Always join 1st stack to begin search.
85+
86+
return kth_next_greater_elements
87+
88+
89+
if __name__ == "__main__":
90+
from doctest import testmod
91+
from timeit import timeit
92+
93+
testmod()
94+
setup = "from __main__ import test_array, test_k, find_kth_next_greater_element"
95+
print(
96+
"find_kth_next_greater_element():",
97+
timeit("find_kth_next_greater_element(test_array, test_k)", setup=setup),
98+
)

0 commit comments

Comments
 (0)