Sunny-117 / js-challenges

✨✨✨ Challenge your JavaScript programming limits step by step

Home Page:https://juejin.cn/column/7244788137410560055

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

最长递增子序列

Nasuke opened this issue · comments

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

参考代码如下:

/**
 * @param {number[]} nums
 * @return {number}
 */
var lengthOfLIS = function(nums) {
    let n = nums.length, res = 0;
    let f = new Array(n).fill(1)

    for(let i = 0; i < n; i++)
        for(let j = 0; j <=i; j++){
            if(nums[j] < nums[i]){
                f[i] = Math.max(f[i], f[j] + 1)
            }
        }
    for(let i = 0; i < n; i++){
        res = Math.max(f[i],res)
    }
    return res
};

动态规划,dp大法

/**
 * 给定一个无序的整数数组,找到其中最长上升子序列的长度。
 * @param nums
 * @returns
 */
const lengthOfLIS = function (nums: number[]): number {
  if (nums.length === 0) return 0;

  const dp = new Array<number>(nums.length).fill(1);
  let maxLen = 1;

  // 从第2个元素开始,遍历整个数组
  for (let i = 1; i < nums.length; i++) {
    // 每遍历一个新元素,都要“回头看”,看看能不能延长原有的上升子序列
    for (let j = 0; j < i; j++) {
      // 若遇到了一个比当前元素小的值,则意味着遇到了一个可以延长的上升子序列,故更新当前元素索引位对应的状态
      if (nums[j] < nums[i]) {
        dp[i] = Math.max(dp[i], dp[j] + 1);
      }
    }

    if (dp[i] > maxLen) {
      maxLen = dp[i];
    }
  }

  return maxLen;
};

// test
console.log(lengthOfLIS([10, 9, 2, 5, 3, 7, 101, 18]));
/**
 * @param {number[]} nums
 * @return {number}
 */
优化查找
思路:维护一个队列,该队列保持递增。如果新的数比队尾要小,那么在队列里找到第一个比他
 大的并且替换调。
var lengthOfLIS = function (nums) {
    if (nums.length === 0) return 0;
    let res = 0;
    let queue = [], index = 0
    const max = (a, b) => a > b ? a : b;
    // 二分查找:查找出第一个比当前数大或者等于的数
    const check = (queue, val, l, r) => {
        let mid = (l + r) >> 1
        if (l >= r) return r
        if (queue[mid] > val) {
            return check(queue, val, l, mid)
        } else if (queue[mid] < val) {
            return check(queue, val, mid + 1, r)
        } else return mid
    }
    queue[0] = nums[0]
    for (let i = 1; i < nums.length; i++) {
        if (queue[index] < nums[i]) {
            queue[++index] = nums[i]
        }
        else {
            let t = check(queue, nums[i], 0, index);
            queue[t] = nums[i]
        }
        res = max(res, queue.length);
    }
    res = max(res, queue.length);
    return res
};