Tanky Woo大牛的介绍:
http://www.wutianqi.com/?p=1850
引出:
问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7….an,求它的一个子序列(设为s1,s2,…sn),使得这个子序列满足这样的性质,s1<s2<s3<…<sn并且这个子序列的长度最长。输出这个最长的长度。(为了简化该类问题,我们将诸如最长下降子序列及最长不上升子序列等问题都看成同一个问题,其实仔细思考就会发现,这其实只是<符号定义上的问题,并不影响问题的实质)
例如有一个序列:1 7 3 5 9 4 8,它的最长上升子序列就是 1 3 4 8 长度为4.
分析:
这题目是经典的DP题目,也可叫作LIS(Longest
Increasing Subsequence)最长上升子序列或者 最长不下降子序列。很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) 。
算法1:
时间复杂度:O(n^2):
我们依次遍历整个序列,每一次求出从第一个数到当前这个数的最长上升子序列,直至遍历到最后一个数字为止,然后再取dp数组里最大的那个即为整个序列的最长上升子序列。我们用dp[i]来存放序列1-i的最长上升子序列的长度,那么dp[i]=max(dp[j])+1,(j∈[1, i-1]); 显然dp[1]=1,我们从i=2开始遍历后面的元素即可。
int LIS(int arr[], int n)
{
int dp[MAX];
for(int i = 1; i <= n; i++)
dp[i] = 0;
int ans = 0;
for(int i = 1; i <= n; i++)
{
dp[i] = 1;
for(int j = 1; j < i; j++)
{
if(arr[i] > arr[j] && dp[j] + 1 > dp[i])
dp[i] = dp[j] + 1;
}
if(dp[i] > ans)
{
ans = dp[i];
}
}
return ans;
}
算法2:时间复杂度:(NlogN):
除了算法一的定义之外,增加一个数组b,b[i]用以表示长度为i最长子序列的最后一个数最小可以是多少。易证:i<j时,b[i]<b[j]。
在二分查找时,一直更新b[]内容,设此时b的总长度为k,
若1. arr[i] >= b[k], 则b[k+1] = arr[i];
若2. arr[i] < b[k], 则在b[1..k]中用二分搜索大于arr[i]的最小值,返回其位置pos,然后更新b[pos]=arr[i]。
// Author: Tanky Woo
// Blog: www.WuTianQi.com
// num为要查找的数,k是范围上限
// 二分查找大于num的最小值,并返回其位置
int bSearch(int num, int k)
{
int low=1, high=k;
while(low<=high)
{
int mid=(low+high)/2;
if(num>=b[mid])
low=mid+1;
else
high=mid-1;
}
return low;
}
int LIS()
{
int k = 1;
b[1] = p[1];
for(int i=2; i<=n; ++i)
{
if(p[i]>=b[k])
b[++k] = p[i];
else
{
int pos = bSearch(p[i], k);
b[pos] = p[i];
}
}
return k;
}
以下是证明b[]的单调递增性:b序列是严格递增的,即b[1] < b[2] < … < b[t]。证明:若b[i] >= b[i + 1],b[i + 1] 是长度为i+1的递增子序列的尾项的最小值,设此序列为x[1]..x[i+1],x[1]..x[i]即构成长度为i的递增子序列,x[i]
< x[i+1] = b[i+1] <= b[i],与b[i]定义不符。
hdoj1257
#include<iostream>
#include<cstring>
using namespace std;
int dp[30005];
int arr[30005];
int n;
int LIS()
{
for(int i=1; i<=n; ++i)
dp[i] = 0;
int ans;
dp[1] = 1;
for(int i=2; i<=n; ++i)
{
ans = dp[i];
for(int j=1; j<i; ++j)
{
if(arr[i] > arr[j] && dp[j] > ans)
ans = dp[j];
}
dp[i] = ans+1;
}
ans = 0;
for(int i=1; i<=n; ++i)
{
if(dp[i] > ans)
ans = dp[i];
}
return ans;
}
int main()
{
freopen("in.txt","r",stdin);
while(cin>>n)
{
memset(dp,0,sizeof(dp));
memset(arr,0,sizeof(arr));
for(int i=1;i<=n;i++)
cin>>arr[i];
cout<<LIS()<<endl;
}
}
分享到:
相关推荐
在算法领域,最长上升子序列(Longest Increasing Subsequence,LIS)问题是一个经典的问题,它在计算机科学中有着广泛的应用,例如在数据结构、排序算法以及动态规划等方面。本篇将详细介绍如何找出一个序列中长度...
### 8596 最长上升子序列 #### 问题描述 给定一个整数序列 \(a_1, a_2, \ldots, a_N\),其中 \(1 \leq N \leq 1000\),每个元素 \(a_i\) 的取值范围为 \(0\) 至 \(10000\)。定义一个序列 \(S = (a_{i_1}, a_{i_2}, ...
输入序列,求最长上升子序列的长度,算法复杂度nlgn
动态规划概念 最长上升子序列 最长公共子序列 矩阵连乘问题 背包问题 树形DP 状态压缩DP
1. 最长上升子序列(Longest Increasing Subsequence,简称LIS)问题: - 这是一个经典的算法问题,指的是在一组数列中找到一个最长的子序列,使得子序列中任意两个数a[i]和a[j]满足i时,都有a[i][j]。 - 在文件...
动态规划的经典题目最长上升子序列,而且是经过二分优化的NlogN复杂度算法
最长上升子序列(Longest Increasing Subsequence,简称 LIS)是一个经典的动态规划问题。给定一个无序的整数数组,找到其中最长上升子序列的长度。 上升子序列指的是一个子序列,它的每个元素都严格大于它前面的...
1259:【例9.3】求最长不下降序列 【题目描述】 设有由n(1≤n≤200)个不相同的整数组成的数列,记为:b(1)、b(2)、……、b(n)且b(i)≠b(j)(i≠j),若存在i1…且有b(i1)(i2)<…(ie)则称为长度为e的不下降序列。程序...
标题中提到的知识点是"C语言:基于c代码实现的最长上升子序列",描述部分则简单地提到了"最长上升子序列"。在给出的内容中,是一段C语言的代码,这段代码实现的是求解一个序列中最长上升子序列的长度。 首先,我们...
### 最长上升子序列(LIS)知识点详解 #### 一、定义与应用场景 最长上升子序列(Longest Increasing Subsequence, 简称LIS)问题是寻找一个序列中最长的递增子序列。这里提到的“子序列”指的是原序列中的一些元素按...
【最长上升子序列】是计算机科学中的一个经典问题,尤其在算法竞赛如CSP-J和CSP-S中常被考察。这个问题的目的是在一个给定的整数序列中找到最长的非降序子序列的长度。这里有两个不同的解决方案,都是用C++编写的。 ...
最长上升子序列(LIS,Longest Increasing Subsequence)是计算机科学中,特别是算法竞赛和信息学领域的一个经典问题。该问题要求在一个给定的序列中找到一个尽可能长的严格递增子序列。例如,对于序列 [10, 9, 2, 5...
下面,我们将讨论动态规划经典问题算法,包括合唱队行、最大 k 乘积、0-1 背包问题、最长上升子序列、田忌赛马、花瓶插花等。 一、合唱队行 合唱队行是动态规划经典问题之一。该问题可以描述为:有 n 个人站在一排...
本题解聚焦于LeetCode的第300题——最长上升子序列(Longest Increasing Subsequence, LIS),这是一个典型的动态规划问题。 动态规划是算法设计的一种策略,通过将复杂问题分解成更小的子问题来解决。在最长上升子...
这些问题是编辑距离问题、货物堆积问题、骑士周游问题、数组分割问题、资源分配问题以及最长上升子序列问题。我们将逐一深入探讨这些知识点。 1. **编辑距离问题**: 编辑距离(Levenshtein Distance)是衡量两个...
最长上升子序列通过本文的介绍,相信你对最长上升子序列问题有了更为深入的了解。无论是从理论角度还是实践角度,最长上升子序列都是一个值得深入研究和探索的问题。希望本文能为你提供有益的参考和启发,助你在算法...
300. 最长上升子序列 给定一个无序的整数数组,找到其中最长上升子序列的长度。 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。 说明: 可能会有多种最长上升子...
3. **最长上升子序列 (LIS)**:对于一个序列S,其最长上升子序列是指S中的一个子序列,该子序列是严格递增的,且长度最长。 #### 三、问题定义 假设我们有两个字符串(或整数序列)a和b,我们的目标是找到这两个...