Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array. Formally the function should: Return true if there exists i, j, k such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false. Your algorithm should run in O(n) time complexity and O(1) space complexity. Examples: Given [1, 2, 3, 4, 5], return true. Given [5, 4, 3, 2, 1], return false.
Naive Solution: use DP, Time O(N^2), Space O(N)
dp[i] represents the length of longest increasing subsequence till i including element i in nums array. dp[i] is initialized to be 1.
dp[i] = max(dp[i], dp[j]+1), where j is an index before i
1 public class Solution { 2 public boolean increasingTriplet(int[] nums) { 3 int[] dp = new int[nums.length]; 4 for (int i=0; i<nums.length; i++) { 5 dp[i] = 1; 6 for (int j=0; j<i; j++) { 7 if (nums[j] < nums[i]) { 8 dp[i] = Math.max(dp[i], dp[j]+1); 9 } 10 if (dp[i] == 3) return true; 11 } 12 } 13 return false; 14 } 15 }
Better Solution: keep two values. Once find a number bigger than both, while both values have been updated, return true.
small: is the minimum value ever seen untill now
big: the smallest value that has something before it that is even smaller. That 'something before it that is even smaller' does not have to be the current min value.
Example:
3,2,1,4,0,5
When you see 5, min value is 0, and the smallest second value is 4, which is not after the current min value.
1 public class Solution { 2 public boolean increasingTriplet(int[] nums) { 3 int small = Integer.MAX_VALUE, big = Integer.MAX_VALUE; 4 for (int n : nums) { 5 if (n <= small) { 6 small = n; 7 } 8 else if (n <= big) { 9 big = n; 10 } 11 else return true; 12 } 13 return false; 14 } 15 }