【LeetCode】300.最长递增子序列——暴力递归(O(n^3)),动态规划(O(n^2)),动态规划+二分法(O(nlogn))
算法新手,刷力扣遇到这题,搞了半天终于搞懂了,来这记录一下,欢迎大家交流指点。
题目描述:
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
解法一:暴力递归
不解释,先暴力搞一下。(时间复杂度O(n^3),不行)
1 class Solution {
2 public:
3 int l(vector<int>& nums) { // 返回以nums[0]开头的最长递增序列长度
4 if (nums.size() < 2)
5 return nums.size();
6 int max_len = 1;
7 for (int i = 1; i < nums.size(); ++ i)
8 if (nums[i] > nums[0]) {
9 vector<int> t{nums.begin() + i, nums.end()};
10 max_len = max(max_len, l(t) + 1);
11 }
12 return max_len;
13 }
14 int lengthOfLIS(vector<int>& nums) { // 所有序列遍历一遍
15 int max_len = 1;
16 for (i = 0; i < nums.size(); ++ i) {
17 vector<int> t(nums.begin() + i, nums.end());
18 max_len = max(max_len, l(t));
19 }
20 return max_len;
21 }
22 };
小优化一下,记忆化搜索。(还是不行,时间复杂度还是太高)
1 class Solution {
2 public:
3 int l(unordered_map<int, int>& map, vector<int>& nums) {
4 if (nums.size() < 2)
5 return nums.size();
6 if (map.find(nums[0]) != map.end()) // 如果已经知道了以某个数开头的元素的最长序列数,直接返回
7 return map[nums[0]];
8 int max_len = 1;
9 for (int i = 1; i < nums.size(); ++ i)
10 if (nums[i] > nums[0]) {
11 vector<int> t{nums.begin() + i, nums.end()};
12 max_len = max(max_len, l(map, t) + 1);
13 }
14 map[nums[0]] = max_len; // 记录以某个数开头的最长递增序列长度
15 return max_len;
16 }
17 int lengthOfLIS(vector<int>& nums) {
18 int max_len = 1;
19 unordered_map<int, int> map; // 哈希表,<开头的数,最长递归序列长度>
20 for (int i = 0; i < nums.size(); ++ i) {
21 vector<int> t(nums.begin() + i, nums.end());
22 max_len = max(max_len, l(map, t));
23 }
24 return max_len;
25 }
26 };
解法二:动态规划
看来暴力是不行滴,还得动态规划。(时间复杂度O(n^2),AC了)
1 class Solution {
2 public:
3 int lengthOfLIS(vector<int>& nums) {
4 vector<int> dp(nums.size(), 0); // 记录以nums[i]为结尾的最长递增子序列长度
5 for (int i = 1; i < nums.size(); ++ i)
6 for (int j = 0; j < i; ++ j) // 找一个最长的递增序列,接到它后面
7 if (nums[j] < nums[i])
8 dp[i] = max(dp[i], dp[j] + 1);
9 return *max_element(dp.begin(), dp.end()) + 1;
10 }
11 };
解法三:动态规划 + 二分查找
动态规划方法是可行的,但是O(n^2)的时间复杂度还是较高,使用二分查找方法可以进一步优化。(时间复杂度O(nlogn),大提升)
1 class Solution {
2 public:
3 int lengthOfLIS(vector<int>& nums) {
4 vector<int> dp(1, *nums.begin()); // 维护一个数组,用来存放最长的递增子序列
5 int left = 0, right = 0, mid = 0;
6 for (int i = 1; i < nums.size(); ++ i) { // 遍历一遍nums寻找每个元素在最长子序列中的插入位置
7 if (nums[i] > *(dp.end() - 1)) { // 如果当前元素比序列中所有元素都大,直接插到末尾
8 dp.push_back(nums[i]);
9 continue;
10 }
11 left = -1; // 否则的话,替换掉序列中第一个大于等于它的元素,这样可以保证得到最长的递增序列
12 right = dp.size();
13 while (left + 1 != right) {
14 mid = (left + right) / 2;
15 if (dp[mid] >= nums[i])
16 right = mid;
17 else
18 left = mid;
19 }
20 dp[right] = nums[i];
21 }
22 return dp.size();
23 }
24 };
【LeetCode】300.最长递增子序列——暴力递归(O(n^3)),动态规划(O(n^2)),动态规划+二分法(O(nlogn))的更多相关文章
- Leetcode 673.最长递增子序列的个数
最长递增子序列的个数 给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[ ...
- Leetcode 300.最长上升子序列
最长上升子序列 给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的 ...
- [LeetCode] 300. 最长上升子序列 ☆☆☆(动态规划 二分)
https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/dong-tai-gui-hua-she-ji-fan ...
- Java实现 LeetCode 673 最长递增子序列的个数(递推)
673. 最长递增子序列的个数 给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递增子序列,分别是 [1, 3, 4, ...
- Java实现 LeetCode 300 最长上升子序列
300. 最长上升子序列 给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,10 ...
- leetcode 300最长上升子序列
用递归DFS遍历所有组合肯定积分会超时,原因是有很多重复的操作,可以想象每次回溯后肯定会有重复操作.所以改用动态规划.建立一个vector<int>memo,初始化为1,memo[i]表示 ...
- Leetcode——300. 最长上升子序列
题目描述:题目链接 给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101], ...
- LeetCode 300. 最长上升子序列(Longest Increasing Subsequence)
题目描述 给出一个无序的整形数组,找到最长上升子序列的长度. 例如, 给出 [10, 9, 2, 5, 3, 7, 101, 18], 最长的上升子序列是 [2, 3, 7, 101],因此它的长度是 ...
- LeetCode 300——最长上升子序列
1. 题目 2. 解答 2.1. 动态规划 我们定义状态 state[i] 表示以 nums[i] 为结尾元素的最长上升子序列的长度,那么状态转移方程为: \[state[i] = max(state ...
随机推荐
- Math.round() 函数返回一个数字四舍五入后最接近的整数。
语法: Math.round(x); 参数:x 返回值:给定数字的值四舍五入到最接近的整数 描述: 如果参数的小数部分大于 0.5,则舍入到相邻的绝对值更大的整数. 如果参数的小数部分小于 0.5,则 ...
- SpringBoot使用@Scheduled创建定时任务
定时任务一般会存在中大型企业级项目中,为了减少服务器.数据库的压力往往会采用时间段性的去完成某些业务逻辑.比较常见的就是金融服务系统推送回调,一般支付系统订单在没有收到成功的回调返回内容时会持续性的回 ...
- Redis 在项目中合理使用经验总结
转自:https://my.oschina.net/u/920698/blog/3031587 背景 Redis 是一个开源的内存数据结构存储系统. 可以作为数据库.缓存和消息中间件使用. 支持多种类 ...
- jQuery中的样式(七):addClass()、removeClass()、toggleClass()、hasClass()、css()、width()、height()等
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- kettle 查询 tinyint 值为 Y,kettle 查询 tinyint 为布尔值
问题解决方法 1.在数据库连接中的[选项]命令参数中加入:tinyInt1isBit = false,如下图: 实际场景:
- C# - 音乐小闹钟_BetaV3.0
时间:2017-11-22 作者:byzqy 介绍: 音乐小闹钟 BetaV3.0 新鲜出炉了,快来围观吧!上效果图: 是不是觉得顿时变得高大上了许多呢?^_^ 工具/原料: (操作系统:Window ...
- TCP/IP以及Socket聊天室带类库源码分享
TCP/IP以及Socket聊天室带类库源码分享 最近遇到个设备,需要去和客户的软件做一个网络通信交互,一般的我们的上位机都是作为客户端来和设备通信的,这次要作为服务端来监听客户端,在这个背景下,我查 ...
- Spring BeanDefinition
定义 /** * A BeanDefinition describes a bean instance, which has property values, * constructor argume ...
- stat 命令家族(4)- 详解 iostat
性能测试必备的 Linux 命令系列,可以看下面链接的文章哦 https://www.cnblogs.com/poloyy/category/1819490.html 介绍 报告 CPU 信息和 I/ ...
- Golang入门学习(二):控制分支
文章目录 @[TOC] 1. 控制分支 1.1 if-else分支 1.2 switch分支 1.4 while 和do...while循环结构 1.5 多种循环结构 1.6 break 1.7 co ...