300. Longest Increasing Subsequence (Solution 2)

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
    }
}

 

posted @ 2021-01-09 13:14  johnny_zhao  阅读(74)  评论(0编辑  收藏  举报