给定一个无序的整数数组,找到其中最长上升子序列的长度。
输入: [10,9,2,5,3,7,101,18]
输出: 4

纯DP

解体思路:利用动态规划的方法,从一个方向遍历数组,每次获取以该位置为子序列结尾的长度。状态表示,利用数组f分别表示以该位结尾的最长上升子序列;状态转移,像前遍历,如果前者比后者小,则取二者最大长度,最后在加一,表示加上当前位。

PS:现在做dp的题自然而然能够想到闫氏DP分析法,首先想到如何用数组表示每个状态,再去思考怎么递推状态。

class Solution {
public int lengthOfLIS(int[] nums) {
int n = nums.length;
// 状态表示
int[] f = new int[n];
int res = 0; for(int i = 0; i < n; i++) {
int cur = 0;
for(int j = i - 1; j >= 0; j--) {
if(nums[i] > nums[j]) {
// 获取前面最长子序列
cur = Math.max(f[j], cur);
}
}
// 状态转移
f[i] = cur + 1;
res = Math.max(f[i], res);
} return res;
}
}

DP + 二分

解题思路:遍历数组,利用一个队列,保存遍历时当前的最长子序列。然后通过二分的方法,查找当前元素在队列中的位置,如果当前元素在队列元素的范围之内,则替换第一个大于等于它的元素,如果当前元素大于队列的最大元素,则直接将当前元素放在最后,同时最长子序列的值增加1。

  • 为什么可以替换中间的值?
    因为替换的是第一个大于等于它的值,这样既可以保持队列递增,还可以降低队列元素的值。
class Solution {
public int lengthOfLIS(int[] nums) {
int[] f = new int[nums.length];
int res = 0;
for(int num : nums) {
int l = 0, r = res;
while(l < r) {
int mid = l + r >> 1;
if(f[mid] >= num) {
r = mid;
} else {
l = mid + 1;
}
} f[r] = num;
if(res == r) res ++;
} return res;
}
}

最新文章

  1. LYDSY模拟赛day1 Tourist Attractions
  2. ArrayList与LinkedList用法与区别
  3. ASP.NET 网站从Sever2003迁移到Sever 2008部署后不能访问
  4. C#基础----Linq之List&lt;T&gt;篇
  5. 160809228_符瑞艺_C语言程序设计实验3 循环结构程序设计
  6. c#下载网页源码的两种方法
  7. NFS文件系统
  8. x5设置经典门户登录
  9. 对比其它软件方法评估敏捷和Scrum
  10. asp.net的CascadingDropDown取值和赋值
  11. Linux_hadoop_install
  12. Apple Swift学习资料汇总
  13. 【GO】关于GO的浅显总结
  14. VB6获取Chrome地址栏的URL信息
  15. Codeforces 1108F MST Unification(最小生成树性质)
  16. IP通信基础课堂笔记----关于数链层
  17. Spring Boot核心配置
  18. ios -- 成员变量、实例变量与属性的区别
  19. Scrapy框架学习笔记
  20. hadoop备战:yarn框架的搭建(mapreduce2)

热门文章

  1. mds/journal.cc: 2929: FAILED assert解决
  2. Idea eclipse 快捷键Debug调试
  3. 网络发布工具 Apache/Nginx
  4. Apache Shiro 反序列化漏洞复现(CVE-2016-4437)
  5. hectf2020部分简单题题解wp
  6. 总是说spring难学?来看完这些spring的注解及其解释,真香!
  7. 思维导图软件iMindMap:生活工作的好帮手
  8. Linux中influx数据库进程杀不掉,父进程为1
  9. css实现元素环形旋转
  10. copy/b一个隐藏文件的小技巧