算法笔记10:最长递增子序列

77 阅读1分钟

300.最长递增子序列

这道题目用 DP 来解决比较简单,对于每一位数字,只要对它前面的每一个数字进行比较即可。从前往后进行的话,前面数字的结果总是已知的,所以就可以递推了。

代码如下:

const lengthOfLIS = (nums) => {
    const memo = Array(nums.length).fill(1);
    for (let i = 1; i < nums.length; i++) {
        const num = nums[i];
        for (let j = 0; j < i; j++) {
            const p = nums[j];
            if (num > p) {
                memo[i] = Math.max(memo[i], 1 + memo[j]);
            }
        }
    }
    return memo.reduce((p, c) => c > p ? c : p, 1);
};

题目里问说能不能考虑 O(n log(n)) 的时间复杂度,确实没想出来。看了拉神的讲解:labuladong.github.io/algo/3/23/7…

感觉主要就是对每个数,找一个它应该在的位置,把那个老的替换掉。整个过程遵守一个由小到大的过程就行了。查找的过程就可以用二分法了,使时间复杂度降低。

代码如下:

const lengthOfLIS = (nums) => {
    const piles = [];
    
    for(let i = 0; i < nums.length; i++) {
        const num = nums[i];
        // find the smallest index of an element in piles
        // which is larger then current number
        
        let l = 0;
        let r = piles.length;
        while (l < r) {
            const mid = Math.floor((l + r) / 2);
            if (num > piles[mid]) {
                l = mid + 1;
            } else {
                r = mid;
            }
        }
        
        piles[l] = num;
    }
    
    return piles.length;
};