前言
hello world欢迎来到前端的新世界
😜当前文章系列专栏:前端面试
🐱👓博主在前端领域还有很多知识和技术需要掌握,正在不断努力填补技术短板。(如果出现错误,感谢大家指出)🌹
💖感谢大家支持!您的观看就是作者创作的动力
题目
用js实现一个整数数组nums,找到其中最长严格递增子序列的长度,子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺利,例如[3,0,2,7]是数组的[0,3,1,6,2,2,7]
加分项 :把算法难度降到O(nlog(n))
代码
方法一,二分查找法
function lengthOfLIS(nums) {
// 特殊情况处理
if (nums.length === 0) {
return 0;
}
// 创建一个数组,用于存储递增子序列的末尾数
const tails = [nums[0]];
// 遍历数组,更新这个数组中的最长递增子序列
for (let i = 1; i < nums.length; i++) {
// 如果当前数比递增子序列的末尾数大,则将当前数加入递增子序列末尾
if (nums[i] > tails[tails.length - 1]) {
tails.push(nums[i]);
} else {
// 如果当前数比递增子序列的末尾数小,则用二分查找找到第一个比它大的数,并替换它
const left = 0, right = tails.length - 1;
while (left < right) {
const mid = Math.floor((left + right) / 2);
if (tails[mid] < nums[i]) {
left = mid + 1;
} else {
right = mid;
}
}
tails[left] = nums[i];
}
}
// 最后,返回递增子序列的长度,即 tails 数组的长度
return tails.length;
}
方法二,动态规划
function lengthOfLIS(nums) {
const len = nums.length;
if (len === 0) return 0;
const dp = new Array(len);
let res = 0;
dp[0] = nums[0];
for (let i = 1; i < len; i++) {
if (nums[i] < dp[0]) {
dp[0] = nums[i]; // 替换掉最小末尾值
} else if (nums[i] > dp[res]) {
dp[++res] = nums[i]; // 如果当前元素大于所有已有递增子序列的末尾值,则直接添加到末尾
} else {
// 使用二分查找找到 nums[i] 在 dp 数组中该插入的位置,并替换掉该位置的值
let left = 0;
let right = res;
while (left < right) {
const mid = Math.floor((left + right) / 2);
if (dp[mid] < nums[i]) {
left = mid + 1;
} else {
right = mid;
}
}
dp[left] = nums[i];
}
}
return res + 1;
}
后言
创作不易,要是本文章对广大读者有那么一点点帮助 不妨三连支持一下,您的鼓励就是博主创作的动力