132 Pattern | Leetcode 456 | Monotonic Stack
Given an array of n
integers nums
, a 132 pattern is a subsequence of three integers nums[i]
, nums[j]
and nums[k]
such that i < j < k
and nums[i] < nums[k] < nums[j]
.
Return true
if there is a 132 pattern in nums
, otherwise, return false
.
Example 1:
Input: nums = [1,2,3,4]
Output: false
Explanation: There is no 132 pattern in the sequence.
Example 2:
Input: nums = [3,1,4,2]
Output: true
Explanation: There is a 132 pattern in the sequence: [1, 4, 2].
Example 3:
Input: nums = [-1,3,2,0]
Output: true
Explanation: There are three 132 patterns in the sequence: [-1, 3, 2], [-1, 3, 0] and [-1, 2, 0].
Constraints:
n == nums.length
1 <= n <= 2 * 10<sup>5</sup>
-10<sup>9</sup> <= nums[i] <= 10<sup>9</sup>
public class Pattern_132 {
/**
* Our condition - nums[i] < nums[k] < nums[j] , where i<j<k
*
* Our approach is to break down the above condition into two set
* Find,
* First, nums[i] < nums[k]
* Second, nums[j] > nums[k]
*
* @param nums - Input integer array
* @return true - if exist
* false - if not exist
*/
public static boolean find132pattern(int[] nums) {
int len = nums.length;
if(len < 3) return false;
int[] minPrefix = new int[len];
// Stack stores the nums[k] values with certain approach
Stack<Integer> stack = new Stack<>();
// Stores minimum value till current element
// Since, nums[i] is the least of (nums[j], nums[k]), i.e., nums[i] < nums[j] && nums[i] < nums[k]
minPrefix[0] = nums[0];
for(int i=1; i<len; i++){
minPrefix[i] = Math.min(minPrefix[i-1], nums[i]);
}
// Traversing from the last, which is an optimal approach to reduce the time complexity
// Now, we have nums[i] which is the least element from {minPrefix} array
// we have nums[j], which is the current traversal element from {nums} array
// We need to find a strategy to get the nums[k], which is in between range (nums[i], nums[j])
// We also need to keep the range of (nums[i], nums[j]) as max as possible to find the value, i.e., minPrefix[] array
for(int j = len-1; j>=0; j--) {
// Our goal is to find element nums[k], which is in between range (nums[i], nums[j])
// If current element is greater than minPrefix[j], => nums[k] > nums[i]
if(nums[j] > minPrefix[j]){
// This is fto find an element(nums[k] in Stack) which is greater than the minPrefix[](nums[i])
while(!stack.isEmpty() && stack.peek() <= minPrefix[j]){
stack.pop();
}
// Now we have found an elemnt nums[i], which is lesser than nums[k] => nums[i] < nums[k]
// Now, we can return true if current (nums[j]) > Stack.peek() (nums[k])
if(!stack.isEmpty() && stack.peek() < nums[j]){
return true;
}
// If not, push that element into stack
stack.push(nums[j]);
}
}
return false;
}
public static void main(String[] args) {
System.out.println(find132pattern(new int[] {1,2,3,4,5}));
System.out.println(find132pattern(new int[] {1,2,3,2,5}));
System.out.println(find132pattern(new int[] {4,3,2,1}));
}
}