输入一串数字例如: 5 6 8 1 3 4 9

输出最长递增子序列长度,示例中即 1 3 4 9或5 6 8 9 ,最大长度为4

public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 几个数字int num = sc.nextInt();// 读取数字int[] arr = new int[num];for (int i = 0; i < num; i++) {arr[i] = sc.nextInt();}// 动态规划dp O(n^2)dp(arr);//二分实现 O(nlog2n)//binarySearch(arr);}

DP实现 复杂度O(n^2)

思路就是双循环,设value[i]为元素arr[i]结尾的子序列的最大长度 , 循环元素i前边的值arr[0- j-1],value[i] = Max(value[i], value[j] + 1);  0<=j<i;

   /*** 动态规划解决,复杂度n2* @param arr*/private static void dp(int[] arr) {int maxLength = 0;// 数组元素value[i]表示以arr[i]为子序列最后一位时,递增子序列的最大长度int[] value = new int[arr.length];// 每次循环获取 以arr[i]为子序列最后一位时,递增子序列最大长度for (int i = 0; i < arr.length; i++) {// 默认都是长度1value[i] = 1;// 循环前i - 1 位value[],找出最大递增序列长度maxvalue,则value[i] = maxvalue + 1;for (int j = 0; j < i; j++) {if (arr[i] > arr[j]) {value[i] = Math.max(value[j] + 1, value[i]);}}// 找出最大的那个maxLength = Math.max(maxLength, value[i]);}System.out.println(maxLength);}

二分查找优化 O(nlog2n)

在动态规划中,内层循环中循环0到i - 1来获取最大的递增序列长度+1,可否换成二分查找log2n来优化呢?但是arr数组是无序的,无法二分查找,需要换种思路

设当前已经求出的最长上升子序列长度为maxLength,声明一个数组value,value[maxLength]表示maxLength长度的子序列最后一位的值
 大致流程:第一个数arr[0]本身就是个子序列,把arr[0]放入value[1],此时最大长度maxLength=1;
接下来的数arr[i]需判断
      1、如果比当前value[maxLength]大,那么表示把arr[i]续到value[maxLength]后可以得到一个更长的子序列,即maxLength++; value[maxLength] = arr[i];
      2、如果比当前value[maxLength]小,那么得从前maxLength个数中找到一个位置j,满足 value[j-1] < arr[i] <= value[j]; 即第一个大于等于arr[i]的数,替换它(value[j] = arr[i]),因为此时以arr[i]为结尾的子序列比以原value[j]结尾的子序列更有“潜力”,因为更小所以有更多的可能得到成更长的子序列
从前maxLength个数中找到一个位置j的过程使用二分查找

   private static void binarySearch(int[] arr) {// 长度加1是为了好理解,value[maxLength]即表示maxLength长度的子序列最后一位的值int[] value = new int[arr.length + 1];// 初始化第一个数int maxLength = 1;value[1] = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] > value[maxLength]) {// 大于目前最大长度的子序列的最后一位,给value[]后边续上maxLength++;value[maxLength] = arr[i];} else {// 小于目前最大长度的子序列的最后一位,查找前边部分第一个大于自身的位置// 更新它int t = find(value, maxLength, arr[i]);value[t] = arr[i];}}System.out.println(maxLength);}// 二分查找private static int find(int[] value, int maxindex, int i) {int l = 1, r = maxindex;while (l <= r) {int mid = (l + r) / 2;if (i > value[mid]) {l = mid + 1;} else {r = mid - 1;}}return l;}

阿里巴巴牛客编程题

小强现在有n个物品,每个物品有x,y两种属性和.他想要从中挑出尽可能多的物品满足以下条件:对于任意两个物品 i 和 j ,满足( i.x < j.x 且 i.y < j.y)或者(i.x > j.x 且 i.y > j.y).问最多能挑出多少物品

第一行输入一个正整数 T.表示有T组数据.
对于每组数据,第一行输入一个正整数N.表示物品个数N.
接下来两行,每行有个N整数.
第一行表示N个节点的X属性.
第二行表示N个节点的Y属性

思路:最长上升子序列的变种,需要保证xy的同升同降,即先将所有物品按x升序排列,随后在无序的y中取一个最长上升子序列即可,同样两种解法,dp和二分,但是本题在牛客上只能二分,dp会报超时。

需要注意的是,在排序过程中,对于相同大小的x,需要将大的y排在前边,因为排在后边,因为x不递增,会导致错误的结果。例如(1,2) (1,3) (1,4),这一组中最长子序列长度正确应为1,但将小y排在前边,所有的 y序列 会算出3的错误结果。

   public static class Good implements Comparable{public int x;public int y;public Good(int xx, int yy) {x = xx;y = yy;}@Overridepublic int compareTo(Object o) {Good good = (Good) o;if (this.x > good.x) {return 1;} else if (this.x < good.x) {return -1;} else {//x相同,y大的放前边if (this.y > good.y) {return -1;} else if (this.y < good.y){return 1;}return 0;}}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int num = sc.nextInt();for (int i = 0; i < num; i++) {int goodsNum = sc.nextInt();int[] linearr1 = new int[goodsNum];int[] linearr2 = new int[goodsNum];for (int j = 0; j < linearr1.length; j++) {linearr1[j] = sc.nextInt();}for (int j = 0; j < linearr2.length; j++) {linearr2[j] = sc.nextInt();}sc.nextLine();Good[] goods = new Good[goodsNum];for (int j = 0; j < goods.length; j++) {goods[j] = new Good(linearr1[j], linearr2[j]);}// 按x升序排序Arrays.sort(goods);// 剩下的就是按y的排列来获取最大上升子序列长度问题,代码与上边两个简单的几乎一致// 动态规划dp O(n^2)dp(goods);// 二分查找优化 O(nlog2n)binarySearch(goods);}}private static void binarySearch(Good[] arr) {int[] value = new int[arr.length +1];int maxLength = 1;value[1] = arr[0].y;for (int i = 1; i < arr.length; i++) {if (arr[i].y > value[maxLength]) {value[++maxLength] = arr[i].y;} else {int t = find(value, maxLength, arr[i].y);value[t] = arr[i].y;}}System.out.println(maxLength);}/*** 动态规划解决,复杂度n2* @param arr*/private static void dp(Good[] arr) {int maxLength = 0;// 数组元素value[i]表示以arr[i]为子序列最后一位时,递增子序列的最大长度int[] value = new int[arr.length];// 每次循环获取 以arr[i]为子序列最后一位时,递增子序列最大长度for (int i = 0; i < arr.length; i++) {// 默认都是长度1value[i] = 1;// 循环第0位到第 i - 1 位value[],找出最大递增序列长度maxvalue,则value[i] = maxvalue + 1;for (int j = 0; j < i; j++) {if (arr[i].y > arr[j].y) {value[i] = Math.max(value[j] + 1, value[i]);}}// 找出最大的那个maxLength = Math.max(maxLength, value[i]);}System.out.println(maxLength);}private static int find(int[] value, int maxindex, int i) {int l = 1, r = maxindex;while (l <= r) {int mid = (l + r) / 2;if (i > value[mid]) {l = mid + 1;} else {r = mid - 1;}}return l;}

参考:https://blog.csdn.net/daoshen1314/article/details/103174215

最长子序列DP和二分法相关推荐

  1. NYOJ-单调递增最长子序列(dp)

    单调递增最长子序列 描述: 求一个字符串的最长递增子序列的长度 如:dabdbf最长递增子序列就是abdf,长度为4 输入: 第一行一个整数0<n<20,表示有n个字符串要处理 随后的n行 ...

  2. 单调递增最长子序列 - 从最长公共子序列到单调递增最长子序列

    最长公共子序列 的 算法思路 在这里 点击进入  将 代码稍微改动一下 就可以   ,   最长公共子序列  是两个 字符串求 公共子序列  , 可以将其中的 一个 改为 从 a 到 z  这样输入另 ...

  3. 动态规划之-----单调递增最长子序列(nyoj17)

    单调递增最长子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 求一个字符串的最长递增子序列的长度 如:dabdbf最长递增子序列就是abdf,长度为4 输入 第一行 ...

  4. 24-单调递增最长子序列(多种解法总结)

    单调递增最长子序列 http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=17 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 ...

  5. AcWing 4489. 最长子序列

    原题链接:4489. 最长子序列 - AcWing题库 给定一个长度为 nn 的严格单调递增的整数序列 a1,a2,-,an. 序列 aa 的子序列可以表示为 ai1,ai2,-,aipai1,ai2 ...

  6. 最长子序列(LCS, LIS, LCIS)

    (一)最长公共子序列(LCS): 我们用Xi代表{x1, x2, .. , xi}, 用Yj代表{y1, y2, .. , yj}.那么,求长度分别为n,m的两个序列X, Y的LCS,就相当于求Xm与 ...

  7. 动态规划----最长子序列

    引出: 问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7-.an,求它的一个子序列(设为s1,s2,-sn),使得这个子序列满足这样的性质,s1<s2<s3<-< ...

  8. 动态规划:最长子序列问题

    关于动态规划中的最长子序列问题有很多优秀的解读,在这里推荐一位博主的关于最长子序列的文章,非常不错,配有大量的图片和文字解答,在这里推荐给大家.本文章转载自这里 1.基本概念 首先需要科普一下,最长公 ...

  9. 【算法】【递归与动态规划模块】两个字符串的公共最长子序列

    目录 前言 问题介绍 解决方案 代码编写 java语言版本 c语言版本 c++语言版本 思考感悟 写在最后 前言 当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批 ...

最新文章

  1. Mac OS X 使用命令sed替换tab
  2. 元宇宙企业大比拼:云宇宙数据中台:iwemeta.com
  3. 实战SSM_O2O商铺_37【商品】商品列表之View层的实现
  4. 1032 挖掘机技术哪家强 (20 分)(c语言)
  5. Log4net使用简介
  6. 【土地评价与土地管理】案例:某地区土地农业利用潜力评价
  7. 数学三大核心领域概述:代数、几何、分析
  8. 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage”包。
  9. abrels.inc.php_fckk.php
  10. Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳实践
  11. web与ai相结合成为趋势_将AI和行为科学相结合可以改变体验
  12. IDEA中部署Tomcat及原理
  13. 炫酷 雨滴桌面设置工具
  14. 全球与中国雷达信标市场深度研究分析报告
  15. 【踩坑】XML转JSON中如何把单个元素转成数组
  16. sqlmap绕过waf的脚本介绍(tamper脚本介绍)
  17. 900行c语言贪吃蛇,挑战CMD版贪吃蛇,能超过我的分算你赢
  18. 【数字图像处理】-图像位数
  19. python floor是什么意思_python里floor怎么用
  20. 当酒品牌遇上爱“微醺”的年轻人,会擦出怎样的火花?

热门文章

  1. 硕士生论文存在的问题
  2. 了解Panda3D引擎的配置变量
  3. 图形学基本知识整理(概述 + 硬件知识)
  4. 有多久没有这么疯狂了?
  5. 设置文件编译规则的makefile---配置编译器环境的c_pp_properties.json---设置的文本配置seting.json
  6. 常见多变量/多元统计分析方法分类图
  7. 安卓手机运行linux
  8. 匈牙利命名法(Hungarian)
  9. 基于云效Flow配置 Jenkins 源
  10. GC5958三相无刷(BLDC)无感正弦波电机驱动芯片 替代APX9358