求最长非降(递增)子序列LIS的长度,及注意事项
非降序列(Increasing Sequence)例如:
(1) 完全递增型序列:S={1,3,6,7,9}
(2) 部分存在等于的序列:S={1,3,3,6,9}
S的非降子序列:由原序列S的元素组成的(且保持元素之间的顺序不变的)组成的序列。
例如S={5,4,7,1,8,6}的子序列包括:
1个元素的:{5},{4},{7},{1},{8},{6} 等6个子序列
2个元素的:{5,7},{5,8},{5,6},{4,7},{4,8},{4,6},{7,8},{1, 8},{1,6} 等
3个元素的:{5,7,8},{4,7,8}
最长非降子序列(Longest Increasing Sequences,LIS),是S的所有非降子序列中包含元素最多的那些子序列,例如上述序列的最长子序列为{5,7,8}和{4,7,8}
而最长非降子序列的长度就是最长非降子序列的元素个数,例如上例中的最长非降子序列的长度为3。
求解序列S的最长非降子序列的长度通常采用动态规划算法:
设d(i)为前i个元素的最长非降子序列的长度,则d(i)=max{ d(j)+1}, 其中 0<=j<=i,且S[j]<S[i]。
然后写出类似这样的代码:
public static void LIS(int []S)
{
int []d=new int[S.length]; for(int i=0;i<S.length;i++)
{
d[i]=1;
for(int j=0;j<i;j++)
{
if(S[j]<=S[i] && d[j]+1<d[i])
{
d[i]=d[j]+1;
}
}
} for(int i=0;i<S.length;i++)
{
System.out.print(d[i]+" ");
}
}
然后,调用该LIS函数,求解。如
int[]seq={5,3,4,8,6,7};
LIS(seq);
会输出:1 1 2 3 3 4 ,代表包含前1个元素的LIS长度为1,包含前2个元素的子序列的LIS长度为1,包含前3个元素的子序列的LIS长度为2,。。。
需要注意的是:上述递推公式,d(i)=max{ d(j)+1}, 其中 0<=j<=i,且S[j]<S[i],只适用于以S[i]作为结尾元素的LIS序列。
而如果去掉以S[i]作为结尾元素这个条件,就不能这么求解。
例如int [ ]seq={5,4,7,1,8,6 }, 用上述程序求解,会输出1 1 2 1 3 2 (即d[3]=1 ,d[5]=2,分别代表包含前4个元素子序列的LIS长度为1,包含前6个元素子序列的LIS长度为2)。但其实包含前4个元素的子序列(即{5,4,7,1})的LIS的长度应该是2,即,d[3]=2, LIS={5,7}或{4,7}, 而 d[5] 应该是3。
问题出在,上述的程序要求LIS以S[i]作为结尾,即LIS的最大元素为S[i],这时d[i]=max{d[j],其中0<=j<=i }是没错的,但如果去掉这个限制条件,就用上面的程序求解就会出错。
那么,如何求解序列S的最长非降子序列的长度(不要求以S的最后一个元素作为LIS的最大元素)?
这通常需要转化为最长公共子序列(LCS)的问题。即:序列S的LIS= 将S排序后的有序序列S' 与 原序列S 的最长公共子序列。
例如,S={5,4,7,1,8,6 } 的LIS为{ 4,7,8 }或{ 5,7,8 },长度为3
对S排序后的S'={ 1,4,5,6,7,8}, S‘与 S的最长公共子序列就是{4, 7, 8 }和{ 5,7,8 }
所以,如何求解序列S的最长非降子序列的长度,首先需要进行排序,然后求LCS的长度即可。
示例代码:
public static void main(String[]args)
{
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int []peaches=new int[n];
for(int i=0;i<n;i++)
{
peaches[i]=sc.nextInt();
}
int []copy=peaches.clone();
quickSort(peaches,0,n-1);
int lisLength=LCS(peaches,copy)
System.out.println("LIS length is"+lisLength);
} public static void quickSort(int []arr,int start,int end)
{
if(start>=end)
return;
int i=start;
int j=end;
int key=arr[i];
while(i<j)
{
while(i<j&&key<=arr[j])
{
j--;
}
arr[i]=arr[j];
while(i<j&&key>arr[i])
{
i++;
}
arr[j]=arr[i];
}
arr[i]=key;
quickSort(arr,start,i-1);
quickSort(arr,i+1,end);
} public static int LCS(int[]a,int[] b)
{
int [][]c=new int[a.length+1][b.length+1];
for(int i=1;i<=a.length;i++)
{
for(int j=1;j<=b.length;j++)
{
if(a[i-1]==b[j-1])
c[i][j]=c[i-1][j-1]+1;
else
c[i][j]=Math.max(c[i-1][j], c[i][j-1]);
}
}
return c[a.length][b.length];
}
如何求LCS的长度?看这里
求最长非降(递增)子序列LIS的长度,及注意事项的更多相关文章
- 最长非降/下降子序列问题(DP)(待续...)
注意:抽象成以下描述即为最长非降/下降子序列问题(一维状态) 问题描述:在一个无序的序列a1,a2,a3,a4…an里,找到一个最长的序列满足:(不要求连续) ai<=aj<=ak…< ...
- 最长非降子序列的N*logN解法
之前讲到过求最长非降子序列的O(N^2)解法. 链接 这次在原来的基础上介绍一下N*logN解法. 该解法主要是维护一个数组minValue,minValue[i]表示最长上身子序列长度为i的数的最小 ...
- 动态规划(DP),最长递增子序列(LIS)
题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...
- 一个数组求其最长递增子序列(LIS)
一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...
- DP:凑零钱问题/最长非降子序列(C++)
你给出一定数额的钱 i 元给我,我利用手中的硬币(m元, j元, k元...)兑换等值的钱给你,要求硬币数最少. 举例:给出1-11的钱,手中硬币有1元,3元,5元. 重点是找到状态和状态转移方程. ...
- 最长非降子序列的O(n^2)解法
这次我们来讲解一个叫做"最长非下降子序列"的问题及他的O(n^2)解法. 首先我们来描述一下什么是"最长非下降子序列". 给你一个长度为n的数组a,在数组a中顺 ...
- 算法之动态规划(最长递增子序列——LIS)
最长递增子序列是动态规划中最经典的问题之一,我们从讨论这个问题开始,循序渐进的了解动态规划的相关知识要点. 在一个已知的序列 {a1, a 2,...an}中,取出若干数组成新的序列{ai1, ai ...
- 最长回文子序列LCS,最长递增子序列LIS及相互联系
最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...
- 动态规划 - 最长递增子序列(LIS)
最长递增子序列是动态规划中经典的问题,详细如下: 在一个已知的序列{a1,a2,...,an}中,取出若干数组组成新的序列{ai1,ai2,...,aim},其中下标i1,i2,...,im保持递增, ...
随机推荐
- 如何在C#/.NET Core中使用责任链模式
原文:Chain Of Responsbility Pattern In C#/.NET Core 作者:Wade 译者:Lamond Lu 最近我有一个朋友在研究经典的"Gang Of F ...
- webpack 和 webpack-cli 安装和使用中出现的问题
因为国内防火墙的原因,建议首先安装 cnpm: 使用 npm install cnpm -g 或者 npm install -g cnpm --registry=https://registry.np ...
- 真正免费,不限页数的PDF转Word工具
真正免费,不限页数的PDF转Word工具 我们知道PDF转Word工具非常多,但大部分都有各种限制,限大小,限页数,加水印等等. 这其中绝大部分其实并不能做到格式完全一样,遇到图片更是直接傻了. 我们 ...
- [hdu5375 Gray code]DP
题意:给一个二进制码,其中有一些位上为'?',对每个问号确定是'0'还是'1',最后以它对应的格雷码来取数,第i位为1则取第i个数,求取得的数的和的最大值. 思路:二进制码B转换成格雷码G的方法是,G ...
- 基于ELK搭建MySQL日志平台的要点和常见错误
第一部分 概括 ELK是集分布式数据存储.可视化查询和日志解析于一体的日志分析平台.ELK=elasticsearch+Logstash+kibana,三者各司其职,相互配合,共同完成日志的数据处理工 ...
- C#枚举高级战术
文章开头先给大家出一道面试题: 在设计某小型项目的数据库(假设用的是 MySQL)时,如果给用户表(User)添加一个字段(Roles)用来存储用户的角色,你会给这个字段设置什么类型?提示:要考虑到角 ...
- buuctf-pwn刷题-axb_2019_heap
版权声明:本文为CSDN博主「L.o.W」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/weixin_441 ...
- python100例 21-30
021 猴子吃桃 题目:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个.以后每天早上都吃了前一天剩下的一半零一个.到第10天早 ...
- Winform GDI+绘图二:绘制旋转太极图
大家好,今天有时间给大家带来Winform自绘控件的第二部分,也是比较有意思的一个控件:旋转太极图. 大家可以停下思考一下,如果让你来绘制旋转的太极图,大家有什么样的思路呢?我今天跟大家展示一下,我平 ...
- 很好的awk教程
讲的内容配合分析web log ,疗效很好! http://www.ibm.com/developerworks/cn/linux/l-cn-awk-httplog/ 出差归来,哈哈,吐槽的不必写了, ...