Iterate through all possible pairs (i, j) to find the maximum width that satisfies nums[i] <= nums[j].
This approach involves nested loops leading to O(n^2) time complexity, which is inefficient for large arrays.
Method 2 - Using right max array and two-pointer technique#
The goal is to find the maximum distance, and instead of explicitly calculating for every index, key is to eliminate redundant calculations for many indices.
For example, in the array [6, 0, 8, 2, 1, 5], once we determine that for number 0, the right end of the ramp (let’s call it j) is 5, we can skip calculations for indices between 0 and 5 concerning j = 5, since their distances to 5 would be less than the distance from 0 to 5.
This is a classical two-pointer problem. The right pointer expands the range, and the left pointer contracts it. The trick is for the left pointer to iterate over the original array, while the right pointer iterates over an array that stores the maximum values on the right for each index.
publicclassSolution {
publicintmaxWidthRamp(int[] nums) {
int n = nums.length;
int[] rMax =newint[n];
// Create an array to store the maximum values to the right of each index rMax[n - 1]= nums[n - 1];
for (int i = n - 2; i >= 0; i--) {
rMax[i]= Math.max(rMax[i + 1], nums[i]);
}
int left = 0, right = 0;
int ans = 0;
// Use the two-pointer technique to find the maximum width rampwhile (right < n) {
while (left < right && nums[left]> rMax[right]) {
left++; // Move left pointer to the right }
ans = Math.max(ans, right - left); // Calculate the width of the current ramp right++; // Move right pointer to the right }
return ans;
}
}
classSolution:
defmaxWidthRamp(self, nums: List[int]) -> int:
n = len(nums)
rMax = [0] * n
# Create an array to store the maximum values to the right of each index rMax[n -1] = nums[n -1]
for i in range(n -2, -1, -1):
rMax[i] = max(rMax[i +1], nums[i])
left =0 right =0 ans =0# Use the two-pointer technique to find the maximum width rampwhile right < n:
while left < right and nums[left] > rMax[right]:
left +=1# Move left pointer to the right ans = max(ans, right - left) # Calculate the width ramp right +=1# Move right pointer to the rightreturn ans
⏰ Time complexity: O(n), because there are two passes over the input array: one to create the rMax array and another to find the maximum width ramp using two pointers.
🧺 Space complexity: O(n) due to the additional rMax array storage.
Sort the indices in a separate array based on the elements of the original array.
For the array [6, 0, 8, 2, 1, 5], the sorted indices array would be [1, 4, 3, 5, 0, 2].
These indices are now ordered according to the values of the elements in non-decreasing order. For any indices i and j where i < j, if index[i] < index[j] (meaning the smaller element appears before the larger element in the original array), it can be a candidate for the solution. Iterate through the array while maintaining the minimum index encountered so far.
publicclassSolution {
publicintmaxWidthRamp(int[] nums) {
int n = nums.length;
Integer[] indices =new Integer[n];
// Populate the indices array with values from 0 to n-1for (int i = 0; i < n; i++) {
indices[i]= i;
}
// Sort indices based on the values in the nums array Arrays.sort(indices, Comparator.comparingInt(i -> nums[i]));
int minIndex = n; // Initialize minIndex to n (outside the array bounds)int maxWidth = 0; // Initialize maxWidth to 0// Traverse the sorted indices to find the maximum width rampfor (int i = 0; i < n; i++) {
int idx = indices[i]; // Current index in the sorted indices array maxWidth = Math.max(maxWidth, idx - minIndex); // Update maxWidth with the maximum width found minIndex = Math.min(minIndex, idx); // Update minIndex with the minimum index encountered }
return maxWidth; // Return the maximum width of the ramp }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classSolution:
defmaxWidthRamp(self, nums: List[int]) -> int:
n = len(nums)
indices = list(range(n))
# Sort indices based on the values in nums indices.sort(key=lambda i: nums[i])
min_index = n
max_width =0# Traverse the sorted indices to find the maximum width rampfor i in range(n):
idx = indices[i]
max_width = max(max_width, idx - min_index)
min_index = min(min_index, idx)
return max_width
Another way is to maintain a stack of elements in decreasing order.
Consider the array: [6, 0, 8, 2, 1, 5]
Decreasing order stack: [6, 0].
There’s no need to add 8 to the stack. For any element on the right where 8 could be part of a solution (as the left end of a ramp), 0 can also serve as the left end and provide a larger ramp length because the index of 0 is less than that of 8. Thus, 8 will never be the left end of the longest ramp.
The same logic applies to 2, 1, and 5.
Once the stack is built, start iterating the array from the end, treating the current element as the right end of the ramp and the stack’s top element as the left end. If the stack’s top element meets the condition, a candidate ramp is found.
The key is: we can now pop that element from the stack. Why? Suppose we are currently at index j and the stack’s top is at index i.
So, the ramp is i..j.
As we iterate backward, the next right end will be j-1. Even if it forms a ramp with i, its length will be shorter than the current ramp (j-i). Thus, there’s no point in keeping 0 in the stack now.
Continue popping elements off the stack whenever a candidate ramp is found, as the current candidate ramp is the best possible ramp using the stack’s top element as the left end.
publicclassSolution {
publicintmaxWidthRamp(int[] nums) {
int n = nums.length;
Deque<Integer> stk =new ArrayDeque<>();
// Create a monotonic decreasing stack with indicesfor (int i = 0; i < n; i++) {
if (stk.isEmpty() || nums[i]< nums[stk.peek()]) {
stk.push(i); // Push the index onto the stack }
}
int maxWidth = 0;
// Traverse the array from the end to find the maximum width rampfor (int i = n - 1; i >= 0; i--) {
while (!stk.isEmpty() && nums[i]>= nums[stk.peek()]) {
// Calculate the width of the ramp and update maxWidth maxWidth = Math.max(maxWidth, i - stk.pop());
}
}
return maxWidth; // Return the maximum width of the ramp found }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classSolution:
defmaxWidthRamp(self, nums: List[int]) -> int:
n = len(nums)
stack = []
# Create a monotonic decreasing stack with indicesfor i in range(n):
ifnot stack or nums[i] < nums[stack[-1]]:
stack.append(i) # Push the index onto the stack max_width =0# Traverse the array from the end to find the maximum width rampfor i in range(n -1, -1, -1):
while stack and nums[i] >= nums[stack[-1]]:
# Calculate the width of the ramp and update max_width max_width = max(max_width, i - stack.pop())
return max_width # Return the maximum width of the ramp found