package LeetCode_300
/**
* 300. Longest Increasing Subsequence
* https://leetcode.com/problems/longest-increasing-subsequence/description/
* Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Note:
1. There may be more than one LIS combination, it is only necessary for you to return the length.
2. Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
* */
class Solution2 {
/*
* solution 2: Patience Sorting, Time:O(nlogn), Space:O(n)
* https://www.cs.princeton.edu/courses/archive/spring13/cos423/lectures/LongestIncreasingSubsequence.pdf
* */
fun lengthOfLIS(nums: IntArray): Int {
val n = nums.size
if (n == 0) {
return 0
}
val list = ArrayList<Int>()
for (i in nums.indices) {
/*
//method 1:
Collections.binarySearch:
* 1. list contains nums[i], return the index of nums[i] in list;
* 2. list not contains nums[i], return ~index, the index is the first number larger than nums[i],
* (if key not found, index start from 1);
* */
/*var x = Collections.binarySearch(list, nums[i])
if (x < 0) {
x = x.inv()
}
if (x == list.size) {
list.add(nums[i])
} else {
list.set(x, nums[i])
}*/
//method 2:
if (list.isEmpty() || list.get(list.lastIndex) < nums[i]) {
list.add(nums[i])
} else {
list.set(findFirstLargeOrEquals(list, nums[i]), nums[i])
}
}
return list.size
}
private fun findFirstLargeOrEquals(list: ArrayList<Int>, target: Int): Int {
var left = 0
var right = list.size - 1
while (left < right) {
val mid = left + (right - left) / 2
if (list.get(mid) < target) {
//search in right side
left = mid + 1
} else {
right = mid
}
}
return left
}
}