算法题解-递增子序列

313 阅读2分钟

题目

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

输入: nums = [10,9,2,5,3,7,101,18]
输出: 4

题解

第一种

我们在函数中声明了两个变量q和tt,q是一个数组用于存储递增子序列,tt是一个指针,指向当前递增子序列的最后一个元素,然后我们使用循环遍历数组nums中的每一个元素,在循环中我们先判断如果q[tt]小于当前元素num或者tt为0则将当前元素num添加到q数组中后并将tt加一,如果当前元素不满足条件则进入循环,该循环用于在q数组中查找一个位置,使得该位置的元素大于等于当前元素num,我们通过不断缩小查找范围来找到合适的位置,在循环中我们先计算中间位置mid,然后判断q[mid]是否小于当前元素num,如果是则将左边界l更新为mid否则就将右边界r更新为mid-1,当循环结束后,找到了合适的位置l,如果q[l]小于当前元素num,则将num插入到q[l+1]的位置,并将q[l+1]更新为q[l+1]和num中的较小值,如果q[l]大于等于当前元素num,则将q[l]更新为num,最后我们将tt变量返回出去即可

var lengthOfLIS = function (nums) {
  let q = []
  let tt = 0
  for (const num of nums) {
    if (q[tt] < num || !tt) {
      q[++tt] = num
      continue
    }
    let l = 1
    let r = tt
    while (l < r) {
      let mid = (l + r + 1) >> 1
      if (q[mid] < num) {
        l = mid
      } else {
        r = mid - 1
      }
    }
    if (q[l] < num) {
      q[l + 1] = Math.min(q[l + 1], num)
    } else {
      q[l] = num
    }
  }
  return tt
};

第二种

我们在函数中先声明了一个变量max默认值为1,用于记录最长递增子序列的长度,然后我们声明一个名为dpMap的Map对象,dpMap用于存储每个位置的最长递增子序列长度,我们默认将数组的第一个元素的索引0作为键,对应的最长递增子序列长度1作为值存入dpMap中,然后我们使用一个循环从数组的第二个元素开始遍历nums数组,在循环中我们先将当前位置的索引i作为键,存入dpMap中,然后我们使用一个嵌套循环来比较dpMap中当前位置i的最长递增子序列长度和之前位置j的最长递增子序列长度加1的大小,来更新dpMap中当前位置i的最长递增子序列长度,然后我们在通过比较max和dpMap中当前位置i的最长递增子序列长度,来更新max的值为当前的最长递增子序列长度,最后我们将max变量返回出去即可

var lengthOfLIS = function(nums) {
    let max = 1;
    let dpMap = new Map();
    dpMap.set(0, 1);
    for(let i = 1; i < nums.length; i++) {
        dpMap.set(i, 1);
        for(let j = 0; j < i; j++) {
            if(nums[i] > nums[j]) {
                const dp = Math.max(dpMap.get(i), dpMap.get(j) + 1);
                dpMap.set(i, dp);
            }
        }
        max = Math.max(max, dpMap.get(i));
    }
    return max;
};

坚持努力,无惧未来!