|
1 | | -from __future__ import annotations |
2 | | - |
3 | | -arr = [-10, -5, 0, 5, 5.1, 11, 13, 21, 3, 4, -21, -10, -5, -1, 0] |
4 | | -expect = [-5, 0, 5, 5.1, 11, 13, 21, -1, 4, -1, -10, -5, -1, 0, -1] |
5 | | - |
6 | | - |
7 | | -def next_greatest_element_slow(arr: list[float]) -> list[float]: |
8 | | - """ |
9 | | - Get the Next Greatest Element (NGE) for each element in the array |
10 | | - by checking all subsequent elements to find the next greater one. |
11 | | -
|
12 | | - This is a brute-force implementation, and it has a time complexity |
13 | | - of O(n^2), where n is the size of the array. |
14 | | -
|
15 | | - Args: |
16 | | - arr: List of numbers for which the NGE is calculated. |
17 | | -
|
18 | | - Returns: |
19 | | - List containing the next greatest elements. If no |
20 | | - greater element is found, -1 is placed in the result. |
21 | | -
|
22 | | - Example: |
23 | | - >>> next_greatest_element_slow(arr) == expect |
24 | | - True |
25 | | - """ |
26 | | - |
27 | | - result = [] |
28 | | - arr_size = len(arr) |
29 | | - |
30 | | - for i in range(arr_size): |
31 | | - next_element: float = -1 |
32 | | - for j in range(i + 1, arr_size): |
33 | | - if arr[i] < arr[j]: |
34 | | - next_element = arr[j] |
35 | | - break |
36 | | - result.append(next_element) |
37 | | - return result |
38 | | - |
39 | | - |
40 | | -def next_greatest_element_fast(arr: list[float]) -> list[float]: |
41 | | - """ |
42 | | - Find the Next Greatest Element (NGE) for each element in the array |
43 | | - using a more readable approach. This implementation utilizes |
44 | | - enumerate() for the outer loop and slicing for the inner loop. |
45 | | -
|
46 | | - While this improves readability over next_greatest_element_slow(), |
47 | | - it still has a time complexity of O(n^2). |
48 | | -
|
49 | | - Args: |
50 | | - arr: List of numbers for which the NGE is calculated. |
51 | | -
|
52 | | - Returns: |
53 | | - List containing the next greatest elements. If no |
54 | | - greater element is found, -1 is placed in the result. |
55 | | -
|
56 | | - Example: |
57 | | - >>> next_greatest_element_fast(arr) == expect |
58 | | - True |
59 | | - """ |
60 | | - result = [] |
61 | | - for i, outer in enumerate(arr): |
62 | | - next_item: float = -1 |
63 | | - for inner in arr[i + 1 :]: |
64 | | - if outer < inner: |
65 | | - next_item = inner |
66 | | - break |
67 | | - result.append(next_item) |
68 | | - return result |
69 | | - |
70 | | - |
71 | | -def next_greatest_element(arr: list[float]) -> list[float]: |
72 | | - """ |
73 | | - Efficient solution to find the Next Greatest Element (NGE) for all elements |
74 | | - using a stack. The time complexity is reduced to O(n), making it suitable |
75 | | - for larger arrays. |
76 | | -
|
77 | | - The stack keeps track of elements for which the next greater element hasn't |
78 | | - been found yet. By iterating through the array in reverse (from the last |
79 | | - element to the first), the stack is used to efficiently determine the next |
80 | | - greatest element for each element. |
81 | | -
|
82 | | - Args: |
83 | | - arr: List of numbers for which the NGE is calculated. |
84 | | -
|
85 | | - Returns: |
86 | | - List containing the next greatest elements. If no |
87 | | - greater element is found, -1 is placed in the result. |
88 | | -
|
89 | | - Example: |
90 | | - >>> next_greatest_element(arr) == expect |
91 | | - True |
92 | | - """ |
93 | | - arr_size = len(arr) |
94 | | - stack: list[float] = [] |
95 | | - result: list[float] = [-1] * arr_size |
96 | | - |
97 | | - for index in reversed(range(arr_size)): |
| 1 | +""" |
| 2 | +Next Greater Element |
| 3 | +-------------------- |
| 4 | +Given an array, find the next greater element for each element in the array. |
| 5 | +The next greater element for an element x is the first greater element on the |
| 6 | +right side of x in the array. If no such element exists, output -1. |
| 7 | +""" |
| 8 | + |
| 9 | +def next_greater_elements(arr): |
| 10 | + stack = [] |
| 11 | + result = [-1] * len(arr) |
| 12 | + |
| 13 | + # Traverse from right to left |
| 14 | + for i in range(len(arr) - 1, -1, -1): |
| 15 | + while stack and stack[-1] <= arr[i]: |
| 16 | + stack.pop() |
98 | 17 | if stack: |
99 | | - while stack[-1] <= arr[index]: |
100 | | - stack.pop() |
101 | | - if not stack: |
102 | | - break |
103 | | - if stack: |
104 | | - result[index] = stack[-1] |
105 | | - stack.append(arr[index]) |
| 18 | + result[i] = stack[-1] |
| 19 | + stack.append(arr[i]) |
106 | 20 | return result |
107 | 21 |
|
108 | 22 |
|
109 | 23 | if __name__ == "__main__": |
110 | | - from doctest import testmod |
111 | | - from timeit import timeit |
112 | | - |
113 | | - testmod() |
114 | | - print(next_greatest_element_slow(arr)) |
115 | | - print(next_greatest_element_fast(arr)) |
116 | | - print(next_greatest_element(arr)) |
117 | | - |
118 | | - setup = ( |
119 | | - "from __main__ import arr, next_greatest_element_slow, " |
120 | | - "next_greatest_element_fast, next_greatest_element" |
121 | | - ) |
122 | | - print( |
123 | | - "next_greatest_element_slow():", |
124 | | - timeit("next_greatest_element_slow(arr)", setup=setup), |
125 | | - ) |
126 | | - print( |
127 | | - "next_greatest_element_fast():", |
128 | | - timeit("next_greatest_element_fast(arr)", setup=setup), |
129 | | - ) |
130 | | - print( |
131 | | - " next_greatest_element():", |
132 | | - timeit("next_greatest_element(arr)", setup=setup), |
133 | | - ) |
| 24 | + sample = [4, 5, 2, 25] |
| 25 | + print("Input:", sample) |
| 26 | + print("Next Greater Elements:", next_greater_elements(sample)) |
| 27 | + # Output: [5, 25, 25, -1] |
0 commit comments