package com.freetymekiyan.algorithms.level.medium;
/**
* Given an unsorted array of integers, find the length of longest increasing subsequence.
* <p>
* For example,
* Given [10, 9, 2, 5, 3, 7, 101, 18],
* The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one
* LIS combination, it is only necessary for you to return the length.
* <p>
* Your algorithm should run in O(n2) complexity.
* <p>
* Follow up: Could you improve it to O(n log n) time complexity?
* <p>
* Tags: Dynamic Programming, Binary Search
* Similar Problems: (M) Increasing Triplet Subsequence, (H) Russian Doll Envelopes
*/
public class LongestIncreasingSubsequence {
/**
* DP.
* Create an array to store the minimum value of a subsequence's maximum at a specific length.
* How to get the value? Use binary search.
* Search for the insertion point of current number.
* Update the number.
* If the insertion point equal to the current size, it means the array can be extended.
* Then the length of Longest Increasing Subsequence can increase by 1.
*/
public int lengthOfLIS(int[] nums) {
int[] tails = new int[nums.length];
int size = 0;
for (int x : nums) {
int l = 0; // Binary search for the insertion point
int r = size;
while (l < r) {
int m = l + (r - l) / 2;
if (tails[m] < x) {
l = m + 1;
} else {
r = m;
}
}
tails[l] = x; // Update tails, won't break its increasing trend
if (l == size) { // x is larger than all elements
size++;
}
}
return size;
}
}