2021-11-05 19:45:37 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2020-03-27 07:16:07 +00:00
|
|
|
arr = [-10, -5, 0, 5, 5.1, 11, 13, 21, 3, 4, -21, -10, -5, -1, 0]
|
2020-03-28 06:24:59 +00:00
|
|
|
expect = [-5, 0, 5, 5.1, 11, 13, 21, -1, 4, -1, -10, -5, -1, 0, -1]
|
2020-03-27 07:16:07 +00:00
|
|
|
|
2020-03-28 06:24:59 +00:00
|
|
|
|
2021-11-05 19:45:37 +00:00
|
|
|
def next_greatest_element_slow(arr: list[float]) -> list[float]:
|
2019-10-18 19:14:01 +00:00
|
|
|
"""
|
2024-10-03 00:18:01 +00:00
|
|
|
Get the Next Greatest Element (NGE) for each element in the array
|
|
|
|
by checking all subsequent elements to find the next greater one.
|
|
|
|
|
|
|
|
This is a brute-force implementation, and it has a time complexity
|
|
|
|
of O(n^2), where n is the size of the array.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
arr: List of numbers for which the NGE is calculated.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
List containing the next greatest elements. If no
|
|
|
|
greater element is found, -1 is placed in the result.
|
|
|
|
|
|
|
|
Example:
|
2020-03-28 06:24:59 +00:00
|
|
|
>>> next_greatest_element_slow(arr) == expect
|
|
|
|
True
|
2019-10-18 19:14:01 +00:00
|
|
|
"""
|
2021-11-05 19:45:37 +00:00
|
|
|
|
2020-03-27 07:16:07 +00:00
|
|
|
result = []
|
2021-11-05 19:45:37 +00:00
|
|
|
arr_size = len(arr)
|
|
|
|
|
|
|
|
for i in range(arr_size):
|
2022-10-13 14:23:59 +00:00
|
|
|
next_element: float = -1
|
2021-11-05 19:45:37 +00:00
|
|
|
for j in range(i + 1, arr_size):
|
2018-10-19 12:48:28 +00:00
|
|
|
if arr[i] < arr[j]:
|
2022-10-13 14:23:59 +00:00
|
|
|
next_element = arr[j]
|
2018-10-19 12:48:28 +00:00
|
|
|
break
|
2022-10-13 14:23:59 +00:00
|
|
|
result.append(next_element)
|
2020-03-27 07:16:07 +00:00
|
|
|
return result
|
|
|
|
|
|
|
|
|
2021-11-05 19:45:37 +00:00
|
|
|
def next_greatest_element_fast(arr: list[float]) -> list[float]:
|
2020-03-27 07:16:07 +00:00
|
|
|
"""
|
2024-10-03 00:18:01 +00:00
|
|
|
Find the Next Greatest Element (NGE) for each element in the array
|
|
|
|
using a more readable approach. This implementation utilizes
|
|
|
|
enumerate() for the outer loop and slicing for the inner loop.
|
|
|
|
|
|
|
|
While this improves readability over next_greatest_element_slow(),
|
|
|
|
it still has a time complexity of O(n^2).
|
|
|
|
|
|
|
|
Args:
|
|
|
|
arr: List of numbers for which the NGE is calculated.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
List containing the next greatest elements. If no
|
|
|
|
greater element is found, -1 is placed in the result.
|
|
|
|
|
|
|
|
Example:
|
2020-03-28 06:24:59 +00:00
|
|
|
>>> next_greatest_element_fast(arr) == expect
|
|
|
|
True
|
2020-03-27 07:16:07 +00:00
|
|
|
"""
|
|
|
|
result = []
|
|
|
|
for i, outer in enumerate(arr):
|
2022-10-13 14:23:59 +00:00
|
|
|
next_item: float = -1
|
2020-03-28 06:24:59 +00:00
|
|
|
for inner in arr[i + 1 :]:
|
2020-03-27 07:16:07 +00:00
|
|
|
if outer < inner:
|
2022-10-13 14:23:59 +00:00
|
|
|
next_item = inner
|
2020-03-27 07:16:07 +00:00
|
|
|
break
|
2022-10-13 14:23:59 +00:00
|
|
|
result.append(next_item)
|
2020-03-27 07:16:07 +00:00
|
|
|
return result
|
|
|
|
|
|
|
|
|
2021-11-05 19:45:37 +00:00
|
|
|
def next_greatest_element(arr: list[float]) -> list[float]:
|
2020-03-27 07:16:07 +00:00
|
|
|
"""
|
2024-10-03 00:18:01 +00:00
|
|
|
Efficient solution to find the Next Greatest Element (NGE) for all elements
|
|
|
|
using a stack. The time complexity is reduced to O(n), making it suitable
|
|
|
|
for larger arrays.
|
|
|
|
|
|
|
|
The stack keeps track of elements for which the next greater element hasn't
|
|
|
|
been found yet. By iterating through the array in reverse (from the last
|
|
|
|
element to the first), the stack is used to efficiently determine the next
|
|
|
|
greatest element for each element.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
arr: List of numbers for which the NGE is calculated.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
List containing the next greatest elements. If no
|
|
|
|
greater element is found, -1 is placed in the result.
|
|
|
|
|
|
|
|
Example:
|
2020-03-28 06:24:59 +00:00
|
|
|
>>> next_greatest_element(arr) == expect
|
|
|
|
True
|
2020-03-27 07:16:07 +00:00
|
|
|
"""
|
2021-11-05 19:45:37 +00:00
|
|
|
arr_size = len(arr)
|
|
|
|
stack: list[float] = []
|
|
|
|
result: list[float] = [-1] * arr_size
|
2020-03-27 07:16:07 +00:00
|
|
|
|
2021-11-05 19:45:37 +00:00
|
|
|
for index in reversed(range(arr_size)):
|
|
|
|
if stack:
|
2020-03-27 07:16:07 +00:00
|
|
|
while stack[-1] <= arr[index]:
|
|
|
|
stack.pop()
|
2021-11-05 19:45:37 +00:00
|
|
|
if not stack:
|
2020-03-27 07:16:07 +00:00
|
|
|
break
|
2021-11-05 19:45:37 +00:00
|
|
|
if stack:
|
2020-03-27 07:16:07 +00:00
|
|
|
result[index] = stack[-1]
|
|
|
|
stack.append(arr[index])
|
|
|
|
return result
|
|
|
|
|
2019-08-19 13:37:49 +00:00
|
|
|
|
2020-03-27 07:16:07 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
from doctest import testmod
|
|
|
|
from timeit import timeit
|
2019-08-19 13:37:49 +00:00
|
|
|
|
2020-03-27 07:16:07 +00:00
|
|
|
testmod()
|
|
|
|
print(next_greatest_element_slow(arr))
|
|
|
|
print(next_greatest_element_fast(arr))
|
|
|
|
print(next_greatest_element(arr))
|
2019-10-05 05:14:13 +00:00
|
|
|
|
2020-03-28 06:24:59 +00:00
|
|
|
setup = (
|
|
|
|
"from __main__ import arr, next_greatest_element_slow, "
|
|
|
|
"next_greatest_element_fast, next_greatest_element"
|
|
|
|
)
|
|
|
|
print(
|
|
|
|
"next_greatest_element_slow():",
|
|
|
|
timeit("next_greatest_element_slow(arr)", setup=setup),
|
|
|
|
)
|
|
|
|
print(
|
|
|
|
"next_greatest_element_fast():",
|
|
|
|
timeit("next_greatest_element_fast(arr)", setup=setup),
|
|
|
|
)
|
|
|
|
print(
|
|
|
|
" next_greatest_element():",
|
|
|
|
timeit("next_greatest_element(arr)", setup=setup),
|
|
|
|
)
|