Every day a Leetcode
题目来源:300. 最长递增子序列
解法1:递归
枚举 nums[i] 作为最长递增子序列的末尾元素,那么需要枚举 nums[j] 作为最长递增子序列的倒数第二个元素,其中 j<i 并且 nums[j]<nums[i]。
问题转化为更小的子问题:求以 nums[j] 为末尾的最长递增子序列,可以用递归来求解
代码:
// 递归class Solution
{
public:int lengthOfLIS(vector<int> &nums){// 特判if (nums.size() == 1)return 1;int n = nums.size();function<int(int)> dfs = [&](int i){int res = 0;for (int j = 0; j < i; j++)if (nums[j] < nums[i])res = max(res, dfs(j));return res + 1;};int ans = 0;for (int i = 0; i < n; i++)ans = max(ans, dfs(i));return ans;}
};
结果:
复杂度分析:
时间复杂度:O(n2),其中 n 是数组 nums 的元素个数。
空间复杂度:O(n),其中 n 是数组 nums 的元素个数。
解法2:动态规划
将
代码:
// 动态规划class Solution
{
public:int lengthOfLIS(vector<int> &nums){// 特判if (nums.size() == 1)return 1;int n = nums.size(), maxLength = 0;// 状态数组,并初始化vector<int> dp(n, 1);// 状态转移for (int i = 0; i < n; i++)for (int j = 0; j < i; j++){if (nums[j] < nums[i])dp[i] = max(dp[i], dp[j] + 1); // 状态转移方程maxLength = max(maxLength, dp[i]);}return maxLength;}
};
结果:
复杂度分析:
时间复杂度:O(n2),其中 n 是数组 nums 的元素个数。
空间复杂度:O(n),其中 n 是数组 nums 的元素个数。
解法3:贪心 + 二分查找
遍历数组 nums:
最后 g 就是最长递增子序列。
对应到代码上,就是把 lower_bound 改成 upper_bound。
代码:
// 贪心 + 二分查找class Solution
{
public:int lengthOfLIS(vector<int> &nums){// 特判if (nums.size() == 1)return 1;int n = nums.size();vector<int> g;for (int i = 0; i < n; i++){int j = lower_bound(g.begin(), g.end(), nums[i]) - g.begin();if (j == g.size())g.push_back(nums[i]);elseg[j] = nums[i];}return g.size();}
};
结果:
复杂度分析:
时间复杂度:O(nlogn),其中 n 是数组 nums 的元素个数。
空间复杂度:O(n),其中 n 是数组 nums 的元素个数。