[路飞]_算法·每日解读--最长递增子序列

490 阅读1分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

题解: leetcode-最长递增子序列

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

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例:

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

根据题意首先进行特殊情况的排除:nums里仅有一个元素时,直接返回本身

const n = nums.length
if(n<=1) return n

接下来选择解题方法,理清思路:

  1. 为了查找并记录最长的递增子序列,需要创建一个新的数组dp来存放筛选后的数据
  2. 创建循环,判断比较,将满足最长子序列的数值添加的dp中的合适位置
cosnt dp = [null,nums[0]];//新建一个dp数组,第一个存储为null,第二个存储为nums的第一个值
let max = 1;//记录dp数组的最大长度
for(let i = 1; i < n; i++){
    //注意:在这里i是从nums的第二个数值开始的,而dp的max为nums为max-1
    //先进行初步判断,如果下一个将要添加到dp数值中的值大于max时,直接进行添加操作
    //添加完成后,执行continue操作,将i的值加1
    if(dp[max] < nums[i]){
        dp[++max] = nums[i];   //++max,将nums[i]添加到下一个,并同时改变max的值
        continue;
    }
    //接下来,进行二分法的查找和比较
    //----
}
  1. nums当中一次取出一个数值,采用二分法与dp数值中的值进行判断比较,确定添加位置
let pos = 0; //初始化pos,来确定nums[i]将要插入的位置
let left = 1,
    right = max,
    mid;
//在这里二分法是对dp数组进行操作
while(left <= right){
    mid = (left + right) >> 1;  //位运算,同理于除以2向下取整  
    //mid = Math.floor((left + right) / 2);
    //判断、比较、记录
    if(num[i] > dp[max]){
        left = mid + 1;//当dp的下一个nums值较中间的值大时,将left移动到mid的右侧
        pos = mid; //pos标记当前的下表位置,nums[i]添加的位置为当前pos的下一个
    }else{
        right = mid - 1;//当dp的下一个nums值较中间的值小时,将right移动到mid的左侧   当right-1小于left时,说明当前的right和left指向同一个数值
    }
}
dp[pos + 1] = nums[i];  //直接进行值替换,二分法分到最后肯定只剩下一种形式:[a] 或 [a,b] 

👆 👆 以上就是个人对【最长递增子序列】的代码解法和方法解读。

如果能够解开您的迷惑,不要忘记一键三连哟!!!

完成代码请移步:GitHub(稍后添加)