一,题目
求一个数组的最长递减子序列
比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2}
求一个数组的最长递增子序列
比如{1,-1,2,-3,4,-5,6,-7}的最长递减子序列为{1,2,4,3,6}
二,递增序列长度求解方法
解法一:
时间复杂度为 o(n^2)
遍历数组序列,每遍历一个数组元素,则求序列到当前位置 最长的递增序列数,用temp[i]存储。
注意,当前的最长递增子序列受已经遍历的最长递增子序列影响,从序列头 再遍历到当前位置的前一个位置,挨个比较 a[j]与a[i](当前元素)大小,遇到小于a[i]且判断需要更新
temp[]数组。
由于这里仅仅是求,最长递增序列的长度,所以仅仅用temp[]存储长度大小。
源码:
#include <iostream>
using namespace std;
int LIS(int array[],int n)
{
int temp[n];//存放当前遍历位置最长序列
for(int i=0;i<n;++i)
{
temp[i]=1; //初始化 默认长度
for(int j=0;j<i;++j) //找出前面最长的序列
{
// 当前值 array[i] 跟已经遍历的值比较,
//大于已经遍历的值且已知递增序列+1 大于当前值则 更新当前最长递增序列值
if(array[i]>array[j] && temp[j]+1 > temp[i] )
{
temp[i] = temp[j] + 1;
}
}
}
int max=temp[0];
for(int k=0;k<n;++k)//找出整个数组中最长的子序列
{
if(max<temp[k])
max=temp[k];
}
return max;
}
int main()
{
int arr[]={1,-1,2,-3,4,-5,6,-7};
int result=LIS(arr,8);
cout<<result<<endl;
}
解法二:时间复杂度任然为 O(n^2)
为了减少比较次数
采用空间换时间的策略。新增一个数组MaxV[],max[i]表示所有长度为i的递增子序列中最大值之间的最小值
nMaxlax记录当前最长子序列
每次遍历一个元素时候,从最长子序列开始遍历,一直到1 比较当前元素值arr[i] 跟MaxV[j]的值,从而更新temp[]最长子序列和nMaxLax和MaxV[]的值
源码:
#include <iostream>
using namespace std;
int LIS(int array[],int n)
{
int temp[n];//存放当前遍历位置最长序列
int MaxV[n]; //最长子序列中最大值之间的最小值
MaxV[1]=array[0];//初始序列长度为1的子序列 中最大值的最小值
MaxV[0]=-9999;//边界值
for(int i=0;i<n;++i)
{
temp[i]=1; //初始化 默认长度
}
int nMaxLis=1;
int j;
for(int i=0;i<n;++i)
{
for(j=nMaxLis;j>=0;--j) //找出前面最长的序列
{
if(array[i]>MaxV[j])//当前值大于长度为j的子序列中最大值之间的最小值
{
temp[i] = j + 1;
break;
}
}
if(temp[i]>nMaxLis)//在最长子序列时停止 (这时只有一个最长的)
{
cout<<"nMaxLIs"<<nMaxLis<<endl;
nMaxLis=temp[i];
MaxV[temp[i]]=array[i];
}
else if(MaxV[j] <array[i] && array[i]<MaxV[j+1])
{
MaxV[j+1]=array[i];
}
}
return nMaxLis;
}
int main()
{
int arr[]={1,-1,2,-3,4,-5,6,-7};
int result=LIS(arr,8);
cout<<result<<endl;
}
解法三:
将内循环查询部分换成二分搜索,则时间复杂度降低为 O(nlogN)
三,递减序列 最长子序列求解方法
用index数组,从大到小排序。然后依次遍历元素,查找元素在index数组中的位置pos ,根据位置来判断当前最长的子序列。
#include<iostream>
#include<cassert>
#include<stack>
using namespace std ;
int BiSearch(int *A,int nTarget,int nLen);
void FindLongestSequence(int *A,int nLen)
{
int *index=new int[nLen];//存放子序列
int *LDS=new int[nLen];
index[0]=A[0];
LDS[0]=1;
int indexLen=1; //最长递增子序列 长度
for (int i=1;i<nLen;i++)
{
//这里是关键,在已经加入的 序列中查找当前序列的插入位置
int pos=BiSearch(index,A[i],indexLen);
index[pos]=A[i];
LDS[i]=pos+1;//记录当前最长序列
if(pos>=indexLen)//插入的当前位置大于最长序列
indexLen++;
}
int ResultLen=indexLen;
for (int i=nLen;i>=0;i--)//记录最长递减子序列
{
if(LDS[i]==ResultLen)
{
index[ResultLen-1]=A[i];
ResultLen--;
}
}
for (int i=0;i<indexLen;i++)
{
cout<<index[i]<<" ";
}
delete []index;
}
int BiSearch(int *A,int nTarget,int nLen)//二分搜索
{
assert(A!=NULL&&nLen>0);
int start=0;
int end=nLen-1;
while (start<=end)
{
int mid=(start+end)/2;
if(nTarget>A[mid])
end=mid-1;
else if(nTarget<A[mid])
start=mid+1;
else
return mid;
}
return start;
}
int main()
{
int A[]={9,4,3,2,5,4,3,2,77,76};
int nLen=sizeof(A)/sizeof(int);
FindLongestSequence(A,nLen);
return 1;
}
分享到:
相关推荐
对于LIS问题,我们可以定义一个数组`dp`,其中`dp[i]`表示以第`i`个元素结尾的最长递增子序列的长度。 **动态规划算法步骤如下:** 1. 初始化`dp`数组,所有元素的初始值为1。因为每个元素至少可以组成长度为1的...
在最长非递增子序列问题中,我们可以定义一个数组dp,其中dp[i]表示以序列中的第i个元素结尾的最长非递增子序列的长度。我们可以通过遍历序列并比较当前元素与之前元素的关系来更新dp数组。 以下是C++实现该算法的...
动态规划是一种将大问题分解为小问题并存储子问题解决方案的技术,它在这里表现为求解最长递减子序列(LDS)来间接得到最长递增子序列(LIS)。这是因为对数列进行逆序处理,求解LDS就相当于求解原始数列的LIS。 ...
在给定的一组数字序列中,最长不减子序列是指这样一个子序列:它的所有元素都是非递减的,且这个子序列的长度是所有非递减子序列中最长的。例如,对于序列 `[10, 9, 2, 5, 3, 7, 101, 18]`,最长不减子序列有 `[2, 5...
在这个问题中,目标是找到一个给定序列中长度最长的单调递增或递减的子序列。这里的“单调”指的是子序列中的元素要么总是递增,要么总是递减。 增量法是一种解决此类问题的有效策略。它通过从小到大的顺序逐步扩展...
### 题目解析:将两个递增的链表合并为一个非递减的链表 #### 一、问题背景与需求分析 本题目要求实现的功能是:输入两个递增的链表,然后通过程序对这两个链表进行排序(虽然在实际应用中,递增的链表已经有序,...
- LCIS问题在寻找两个序列的最长递增子序列,要求这个子序列在两个序列中都是递增的。 - 解决方法结合LCS和LIS的思想,首先计算两个序列的LCS长度,然后分别计算两个序列的LIS,最后找到LCS与LIS的交集作为LCIS。 ...
4) 单选题4:当输入的d[i]是严格单调递减序列时,第17行的“swap”平均执行次数。答案是O(n),因为在递减序列中,第一次划分后就直接找到目标,所以交换次数为n。 5) 单选题5:若输入的d[i]为i,即数组为1到n的序列...
本题要求实现一个函数,将两个链表表示的递增整数序列合并为一个非递减的整数序列。L1和L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1和L2合并为一个非递减的整数序列。应直接使用原...
在Oracle数据库中,序列(Sequences)是一种自动递增或递减的数字生成器,常用于主键生成或者自增字段。批量修改Oracle序列值的需求可能出现在数据迁移、恢复或测试环境中,确保序列与实际数据匹配。这篇博客分享的...
具体到LIS问题,我们可以定义一个数组dp,其中dp[i]表示以序列中的第i个元素结尾的最长上升子序列的长度。初始情况下,所有dp[i]都为1,因为每个元素自身都可以构成一个长度为1的上升子序列。然后,对于每个元素,...
13. 第十三道题中,每两项的乘积加上第三项的两倍等于第四项。 14. 第十四题可以用多种方法解答,例如作差、寻找平方关系或立方关系。 15. 第十五道题中,每个数字的各个数字之和都是质数。 16. 第十六道题是交错...
### 基于链表的两个非递减有序序列的合并 #### 问题背景与目标 本篇文章讨论的问题是:给定两个递增的整数序列A和B,利用链表来表示这两个序列,并实现一个算法,将这两个序列合并成一个新的递增有序序列C。在合并...
这些数值可以是递增或递减的,并且可以根据设定的最小值和最大值循环生成。序列对于需要唯一标识符的应用场景特别有用,比如为表中的记录分配唯一的ID。 #### 创建序列 创建序列的基本语法如下: ```sql CREATE ...
给定一个单调递增的整数序列,问某个整数是否在序列中
- `INCREMENT BY n` 指定序列每次递增或递减的步长,默认值为1。 - `START WITH n` 指定序列的初始值,默认值取决于`MINVALUE`和`MAXVALUE`的设置。 - `MAXVALUE n` 设置序列的最大值,`NOMAXVALUE`表示无最大值...
1. **INCREMENT BY**:指定每次调用序列时递增或递减的值,默认为1。 2. **MINVALUE 和 MAXVALUE**:设置序列最小值和最大值,默认无最小值(NOMINVALUE),最大值为最大整数(NOMAXVALUE)。 3. **START WITH**:...
在Oracle数据库中,序列(Sequences)是一种自动递增或递减的数字生成器,常用于为表的主键字段生成唯一的标识符。在大型数据库系统中,它们是管理序列化和唯一性的重要工具。本篇文章将深入探讨如何在Oracle中生成...
### 两个递减线性表的合并 #### 题目背景 在计算机科学与技术领域,链表是一种常见的数据结构,在很多实际问题中都有着广泛的应用。本题目旨在通过两个递减有序的单链表的合并操作来加深对链表基本操作的理解与...
在Oracle数据库系统中,序列(Sequences)提供了一种自动递增或递减数值的方式,这对于插入新记录时自动生成唯一的ID非常有用,尤其是对于那些频繁插入数据的大型表。 序列的工作原理是,当你需要一个值时,通过...