|
| 1 | +# Next Greater Element I |
| 2 | +You are given two arrays nums1 and nums2 where nums1 is a subset of nums2. For each element in nums1, find the next greater element in nums2. The Next Greater Element of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, return -1 for this number. |
| 3 | + |
| 4 | +### Constraints: |
| 5 | +- 1 <= nums1.length <= 1000 |
| 6 | +- 1 <= nums2.length <= 1000 |
| 7 | +- 0 <= nums1[i], nums2[i] <= 10^4 |
| 8 | +- All elements in nums1 and nums2 are unique. |
| 9 | +- All the elements of nums1 also appear in nums2. |
| 10 | + |
| 11 | +### Examples |
| 12 | +```javascript |
| 13 | +Input: nums1 = [4,1,2], nums2 = [1,3,4,2] |
| 14 | +Output: [-1,3,-1] |
| 15 | +Explanation: |
| 16 | +For 4, there is no next greater number in nums2. |
| 17 | +For 1, the next greater number is 3. |
| 18 | +For 2, there is no next greater number. |
| 19 | + |
| 20 | +Input: nums1 = [2,4], nums2 = [1,2,3,4] |
| 21 | +Output: [3,-1] |
| 22 | +Explanation: |
| 23 | +For 2, the next greater number is 3. |
| 24 | +For 4, there is no next greater number. |
| 25 | +``` |
| 26 | + |
| 27 | +## Approaches to Solve the Problem |
| 28 | +### Approach 1: Brute Force |
| 29 | +##### Intuition: |
| 30 | +The brute-force solution involves iterating through each element in nums1 and searching for the next greater element in nums2. For each element in nums1, we find its position in nums2, then scan to the right to find the next greater element. |
| 31 | + |
| 32 | +Steps: |
| 33 | +1. For each element in nums1, find its position in nums2. |
| 34 | +2. Start from that position in nums2 and search to the right for the next greater element. |
| 35 | +3. If no greater element is found, return -1 for that element. |
| 36 | +##### Time Complexity: |
| 37 | +O(m * n), where m is the length of nums1 and n is the length of nums2. For each element in nums1, we may have to search through all of nums2. |
| 38 | +##### Space Complexity: |
| 39 | +O(1), as we only need a few variables to track indices and the current next greater element. |
| 40 | +##### Python Code: |
| 41 | +```python |
| 42 | +def nextGreaterElement(nums1, nums2): |
| 43 | + result = [] |
| 44 | + |
| 45 | + for num in nums1: |
| 46 | + found = False |
| 47 | + for i in range(len(nums2)): |
| 48 | + if nums2[i] == num: |
| 49 | + for j in range(i + 1, len(nums2)): |
| 50 | + if nums2[j] > num: |
| 51 | + result.append(nums2[j]) |
| 52 | + found = True |
| 53 | + break |
| 54 | + if not found: |
| 55 | + result.append(-1) |
| 56 | + break |
| 57 | + |
| 58 | + return result |
| 59 | +``` |
| 60 | + |
| 61 | +### Approach 2: Stack with Hash Map (Optimal) |
| 62 | +##### Intuition: |
| 63 | +The brute-force approach is inefficient because it searches nums2 for the next greater element repeatedly. A more efficient approach is to use a monotonic stack and a hash map. The stack helps us keep track of elements in nums2 for which we haven't yet found the next greater element, and the hash map stores the next greater element for each number. |
| 64 | + |
| 65 | +1. Traverse nums2 from right to left. |
| 66 | +2. Use the stack to find the next greater element for each number: |
| 67 | + - If the stack is non-empty and the top of the stack is less than or equal to the current number, pop the stack. |
| 68 | + - The current number's next greater element is at the top of the stack. |
| 69 | +Push the current number onto the stack. |
| 70 | +3. After processing nums2, use the hash map to quickly find the next greater element for each number in nums1. |
| 71 | + |
| 72 | +Steps: |
| 73 | +1. Traverse nums2 from right to left. |
| 74 | +2. Use a stack to maintain the next greater element candidates. |
| 75 | +3. Use a hash map to store the next greater element for each number in nums2. |
| 76 | +4. For each element in nums1, look up the next greater element from the hash map. |
| 77 | +### Visualization |
| 78 | +For nums2 = [1, 3, 4, 2]: |
| 79 | +```rust |
| 80 | +Stack process: |
| 81 | +Start from the rightmost element: 2 → push 2 onto the stack. |
| 82 | +Move to 4 → no elements in the stack are greater than 4 → push 4 onto the stack. |
| 83 | +Move to 3 → next greater element is 4 → push 3 onto the stack. |
| 84 | +Move to 1 → next greater element is 3 → push 1 onto the stack. |
| 85 | + |
| 86 | +Hash map after processing: {2: -1, 4: -1, 3: 4, 1: 3} |
| 87 | +``` |
| 88 | +##### Time Complexity: |
| 89 | +O(m + n), where m is the length of nums1 and n is the length of nums2. We traverse nums2 once and process nums1 in constant time using the hash map. |
| 90 | +##### Space Complexity: |
| 91 | +O(n), where n is the length of nums2. The stack and hash map both use space proportional to the size of nums2. |
| 92 | +##### Python Code: |
| 93 | +```python |
| 94 | +def nextGreaterElement(nums1, nums2): |
| 95 | + # Dictionary to store the next greater element for each number in nums2 |
| 96 | + next_greater = {} |
| 97 | + stack = [] |
| 98 | + |
| 99 | + # Traverse nums2 from right to left |
| 100 | + for num in reversed(nums2): |
| 101 | + # Pop elements from the stack until we find a greater element or the stack is empty |
| 102 | + while stack and stack[-1] <= num: |
| 103 | + stack.pop() |
| 104 | + |
| 105 | + # If the stack is not empty, the top of the stack is the next greater element |
| 106 | + next_greater[num] = stack[-1] if stack else -1 |
| 107 | + |
| 108 | + # Push the current number onto the stack |
| 109 | + stack.append(num) |
| 110 | + |
| 111 | + # Use the dictionary to find the next greater element for each number in nums1 |
| 112 | + return [next_greater[num] for num in nums1] |
| 113 | +``` |
| 114 | +### Edge Cases: |
| 115 | +1. Empty Input: If either nums1 or nums2 is empty, the result should also be an empty list. |
| 116 | +2. No Greater Element: If a number in nums2 does not have a greater element to its right, the result should be -1 for that number. |
| 117 | +3. Single Element: If nums1 or nums2 has a single element, the result will either be -1 or the only element itself. |
| 118 | +## Summary |
| 119 | + |
| 120 | +| Approach | Time Complexity | Space Complexity | |
| 121 | +|-----------------------------------|-----------------|------------------| |
| 122 | +| Brute Force | O(m * n) | O(1) | |
| 123 | +| Stack with Hash Map (Optimal) | O(m + n) | O(n) | |
| 124 | + |
| 125 | +The Stack with Hash Map approach is the most efficient and optimal solution. It uses a monotonic stack to keep track of elements that are waiting for their next greater element and processes the input arrays in linear time. |
0 commit comments