leetcode题解-300. Longest Increasing Subsequence

题目:

Given an unsorted array of integers, find the length of longest increasing subsequence.

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.

Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

这道题目是要求一个数组中增序部分的最大长度,第一眼看到这个题目没有什么思路,究竟怎样能够将增序转化成程序可以表达的语言呢??主要问题集中在如果后面的元素比前面某个元素小时应该如何处理==后来看别人的解决方案真的是很巧妙,将问题转化成一个说不出来的东西==#恩,反正不知道别人是怎么想的。代码如下所示:

    public static int lengthOfLIS(int[] nums) {
        //用来存储当前的增序数组,初始化为全0
        int [] res = new int[nums.length];
        int len = 0;
        //对nums中的每个元素找到其相应的插入位置
        for(int x:nums){
            //使用二叉搜索找到x应该插入的位置索引,如果没有相等元素则返回low+1的负值
            int i = Arrays.binarySearch(res, 0, len, x);
            //转换为正数
            if(i < 0) i = -(i+1);
            //将x插入相应位置,注意这里如果x比前面元素小,则对其进行替换
            res[i] = x;
            //len保存当前最大的增序数组长度,只有当i等于len时才会进行加一操作。
            if(i == len) len ++;
        }
        return len;
    }

还有一种改进,当下一个要判断的元素比res最后一个元素还要大时,不需要使用二叉搜索直接放在最后即可,如下,效率会有所提升:

    public static int findPositionToReplace(int[] a, int low, int high, int x) {
        int mid;
        while (low <= high) {
            mid = low + (high - low) / 2;
            if (a[mid] == x)
                return mid;
            else if (a[mid] > x)
                high = mid - 1;
            else
                low = mid + 1;
        }
        return low;
    }

    public static int lengthOfLIS1(int[] nums) {
        if (nums == null | nums.length == 0)
            return 0;
        int n = nums.length, len = 0;
        int[] increasingSequence = new int[n];
        increasingSequence[len++] = nums[0];
        for (int i = 1; i < n; i++) {
            if (nums[i] > increasingSequence[len - 1])
                increasingSequence[len++] = nums[i];
            else {
                int position = findPositionToReplace(increasingSequence, 0, len - 1, nums[i]);
                increasingSequence[position] = nums[i];
            }
        }
        return len;
    }

当然,上面两种方案都是o(nlogn)的时间复杂度,还有一种o(n2)的解决方法,如下所示:

    public int lengthOfLIS(int[] nums) {
        int N = nums.length;
        if (N == 0) return 0;
        int[] dp = new int[N];
        Arrays.fill(dp, 1);
        int res = 1;
        for (int i = 1; i < N; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[j] < nums[i]) {
                    dp[i] = Math.max(dp[j] + 1, dp[i]);
                }
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }

你可能感兴趣的:(leetcode刷题)