《LeetCode之每日一题》:107.最长递增子序列
Posted 是七喜呀!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:107.最长递增子序列相关的知识,希望对你有一定的参考价值。
题目链接: 最长递增子序列
有关题目
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。
例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
示例 2:
输入:nums = [0,1,0,3,2,3]
输出:4
示例 3:
输入:nums = [7,7,7,7,7,7,7]
输出:1
提示:
1 <= nums.length <= 2500
-10^4 <= nums[i] <= 10^4
题解
法一:动态规划
思路:
dp[i]:表示前i个(包含i)数组元素中升序最大递增子序列
int lengthOfLIS(int* nums, int numsSize){
int dp[numsSize];
int ans = 0;
for (int i = 0; i < numsSize; i++){
dp[i] = 1;//初始化为1
for (int j = 0; j < i; j++){
if (nums[j] < nums[i]){
//nums 10 9 2 5 3 7 101
//dp 1 1 1 2 2 3 4
dp[i] = fmax(dp[i],dp[j] + 1);
}
}
ans = fmax(ans,dp[i]);//记录最大值
}
return ans;
}
方法二:贪心 + 二分查找
思路:贪心,使上升子序列尽可能的长
序列上升得尽可能慢,因此我们希望每次在上升子序列最后加上的那个数尽可能的小
数组 d[i]表示长度为 i 的最长上升子序列的末尾元素的最小值,
即在数组 1,2,3,4,5,6中长度为3的上升子序列
可以为 1,2,3也可以为 2,3,4等等但是d[3]=3,
即子序列末尾元素最小为3。
代码一:
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
int len = 1;
vector d(n + 1, 0);
d[len] = nums[0];//初始化长度为 1 的最长上升子序列的末尾元素的最小值为nums[0]
for (int i = 1; i < nums.size(); i++){
if (nums[i] > d[len]){
d[++len] = nums[i];
}
else{
int l = 1, r = len, pos = 0; 如果找不到说明所有的数都比 nums[i] 大,此时要更新 d[1],所以这里将 pos 设为 0
while(l <= r){
int mid = (l + r) >> 1;
if (nums[i] > d[mid]){//找到小于nums[i]的
pos = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
d[pos + 1] = nums[i];//下一个位置就是大于等于nums[i]的
}
}
return len;//vector开辟d时,可以直接返回d.size();
}
};
代码二:
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> d;
for (int& num : nums){
auto it = lower_bound(d.begin(), d.end(), num);//注意lower_bound与up_bound的用法
//前者找到大于等于num的数,后者找到大于num的数
if (it != d.end()){
*it = num;
}
else
d.push_back(num);
}
return d.size();
}
};
代码三:C
int lower_bound(int d[], int dSize, int target){
int l = 0, r = dSize - 1, pos = dSize;
while(l <= r){
int mid = (l + r) >> 1;
if (d[mid] >= target){
pos = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
return pos;
}
int lengthOfLIS(int* nums, int numsSize){
int d[numsSize], dSize = 1;
d[0] = nums[0];
for (int i = 1; i < numsSize; i++){
int num = nums[i];
int it = lower_bound(d,dSize,num);//找到第一个大于等于
if (it != dSize){
d[it] = num;
} else {
d[dSize++] = num;
}
}
return dSize;
}
以上是关于《LeetCode之每日一题》:107.最长递增子序列的主要内容,如果未能解决你的问题,请参考以下文章
leetcode 1月12日每日一题 334. 递增的三元子序列