问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

LIS算法的介绍

发布网友 发布时间:2022-04-12 14:28

我来回答

2个回答

懂视网 时间:2022-04-12 18:50

最长上升子序列 概念 维基百科-Longest Increasing Subsequence 算法一:动态规划 数据定义: a[] : 输入序列 d[] : 保存最长升序子序列的子问题。 d[i] 表示以a[i]结尾的最长子序列的长度。 d[]初始化为1。因为子序列最短也是1。 n : a 和 d的长度 状态转移

最长上升子序列

概念 维基百科->Longest Increasing Subsequence


算法一:动态规划

数据定义:

a[] : 输入序列

d[] : 保存最长升序子序列的子问题。

d[i] 表示以a[i]结尾的最长子序列的长度。

d[]初始化为1。因为子序列最短也是1。

n : a 和 d的长度

状态转移方程:

d[0] = 1 当i = 0

d[i] = 1 + max{d[j], a[i] > a[j] && 0 <= j < i) 当0

注解:在序列a[0],a[1],a[2],...,a[i-1]中找到最长的一个上升子序列,并且a[i]可以添加在它的末尾,使成为一个更长的上升子序列

时间复杂度分析:

求解一个d[i]需要一个循环取最大值,时间复杂度为O(n),所以总的时间复杂度是 O(n^2)。

程序使用双重循环构造d数组,最后遍历d数值去最大值。


-------------------------------------华丽的分割线------------------------------------------


算法二:贪心 + 二分搜索

数据定义补充:

开一个栈,将a[0]入栈,每次取栈顶元素top和读到的元素a[i](0 top 则将a[i]入栈;如果a[i]<= top则二分查找栈中的比a[i]大的第1个数,并用a[i]替换它。 最长序列长度即为栈的大小top。

这是很好理解的,对于x和y,如果x < y且stack[y] < stack[x],用stack[x]替换stack[y],此时的最长序列长度没有改变,但序列继续变长的'潜力'增大了。

举例:原序列为1,5,8,3,6,7

开始1,5,8相继入栈,此时读到3,用3替换5,得到1,3,8;

再读6,用6替换8,得到1,3,6;

再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。


伪代码描述:

初始化栈s

top = 0;

s[top] = a[i];

for (i = 1; i < n; i++)

if a[i] > s[top] // 将a[i]接在s[top]所代表的子串之后得到一个更长的子序列

top = top + 1

b[top] = a[i]

else

使用二分查找到这样一个j,使得s[j] < a[i] && a[i] <= s[j + 1]

s[j + 1] = a[i]

return : top + 1

算法分析:

内层循环由于b序列的严格递增性,可以使用二分查找,时间复杂度为O(log n),乘以外层循环,最终时间复杂度为O(n log n)。


注意:当出现1,5,8,2这种情况时,栈内最后的数是1,2,8不是正确的序列,难道错了?

分析一下,我们可以看出,虽然有些时候这样得不到正确的序列,但最后算出来的个数是没错的,为什么呢?

想想,当a[i]>top时,总个数直接加1,这肯定没错;但当a[i]

这两种情况的分析可以看出,如果只求个数的话,这个算法比较高效;但如果要求打印出序列时,就只能用动态规划了。


附上C++代码:

#include 
#include 
using namespace std;
//dp[i] 表示以A[0~i]的最长上升子序列的长度
//dp[0] = 1 当i=0
//dp[i] = 1 + max{dp[j], 0= 0) {
		s.push(seq[k]);
		k = pre[k];
	}
	while (!s.empty()) {
		cout << s.top() << "|";
		s.pop();
	}
	cout << endl;
	delete[] dp;
	delete[] pre;
	return max;
}

//找到一个j满足 array[j] < key <= array[j+1] 区间二分搜索
//返回j+1
int binary_search(int array[], int key, int low, int high) {
	while (low <= high) {
		int mid = (low + high) / 2;
		if (array[mid] < key && key <= array[mid+1]) { 
			//由于array严格单调递增,又key >= array[high]
			//mid+1不会溢出,想想为什么
			return mid + 1;
		}
		if (array[mid] < key) {
			low = mid + 1;
		} else {
			high = mid - 1;
		}
	}
}

int lis_greedy(int seq[], int n) {
	int top = 0;
	int* stack = new int[n];
	for (int i = 0; i < n; ++i) {
		stack[i] = 0;
	}
	stack[top] = seq[0];
	for (int i = 0; i < n; ++i) {
		if (seq[i] > stack[top]) {
			//如果seq[i]大于栈顶元素,则入栈
			stack[++top] = seq[i];
		} else {
			//从栈底开始,找到第一个>=seq[i]的元素所在位置
			int replace = binary_search(stack, seq[i], 0, top);
			stack[replace] = seq[i];
		}
	}
	for (int i = 0; i <= top; i++) {
		cout << stack[i] << "|";
	}
	cout << endl;
	delete[] stack;
	return top + 1;
}

int main(int argc, char* argv[]) {
	//int arr[] = {6,3,7,11,12,10,1,13,8,5,4,15,14,9,2};
	int arr[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
	int len = sizeof(arr) / sizeof(int);
	cout << len << endl;
	cout << lis_dp(arr, len) << endl;
	cout << lis_greedy(arr, len) << endl;
	return 0;
}
/* 第一组测试数据
15
6|7|11|12|13|15|
6
1|2|8|9|13|14|
6
*/
从测试结果看出,虽然算法一和算法二给出的长度值相等,但是算法二给出的序列顺序与原来的不符。


参考:

http://www.cnblogs.com/zhtzhl/archive/2012/08/03/2622219.html

http://www.cnblogs.com/zhanglanyun/archive/2011/09/09/2172809.html

http://hi.baidu.com/rffffffff007/item/75353d0c77192810addc70b6

热心网友 时间:2022-04-12 15:58

LIS(Longest Increasing Subsequence)最长上升(不下降)子序列,有两种算法复杂度为O(n*logn)和O(n^2)。在上述算法中,若使用朴素的顺序查找在D1..Dlen查找,由于共有O(n)个元素需要计算,每次计算时的复杂度是O(n),则整个算法的时间复杂度为O(n^2),与原来算法相比没有任何进步。但是由于D的特点(2),在D中查找时,可以使用二分查找高效地完成,则整个算法时间复杂度下降为O(nlogn),有了非常显著的提高。需要注意的是,D在算法结束后记录的并不是一个符合题意的最长上升子序列!算法还可以扩展到整个最长子序列系列问题。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
ef英语哪个好 EF英孚英语培训怎么样? 英孚英语好不好 EF英孚教育到底好不好 大佬们,麦芒7和荣耀10那个值得入手?2500以下的机子还有啥好推荐的么... 介绍几款2500元以前的手机 像素一定要高 其他的不做要求 近期想入手一部安卓手机,价格2200到2500左右…买HTC desire Z还是 三星... 笔记本忘记开机密码怎么办急死了 笔记本电脑屏幕开机锁忘记密码 怎么办?急死了 华硕笔记本电脑开机密码忘记了怎样找回?系统是Windows 7旗舰版... 一周汽车圈丨小鹏汽车即将赴美上市,新款马自达CX-4即将上市…… 证金(福建)贵金属投资有限公司怎么样? 西红柿尖椒炒鸡蛋怎么做如何做好吃 武都区有公共基础知识的培训班吗?有知道的麻烦告诉我电话。谢谢!! 西红柿辣椒炒鸡蛋怎么做好吃,西红柿辣椒炒 参加教师招聘的公共基础知识、哪个辅导班好啊 跪求郑州市或者南阳市公共基础知识培训班 事业单位公共基础知识辅导,那个机构辅导效果比较好? 陕西事业单位考试,公共基础知识笔试培训,效果如何,有没有必要 陇南地区有公共基础知识培训班吗?号码 乒乓,729-8es省套和08ES差距大吗 乒乓球运动对器材最基本的要求 宣城有公共基础知识二的培训辅导班吗? 无机胶水一般多久才干 遵义市培训公共基础知识的机构有哪些? 西知教育公共基础知识辅导班怎么样? 请问改用无机胶水后还需要灌胶吗? 你知道哪里有公共基础知识的培训班吗? 蝴蝶TO5胶皮能用有机胶水吗? 公共基础知识怎么学?有推荐的老师吗? 微信微众银行怎么关闭绑定的 微信微众银行怎么关闭绑定的? 哪个银行能靠谱点? 高中英语GVC是什么 gvc钻狗是什么牌子??? 英语GVC是什么题 马自达GVC是什么原理 纪梵希联名涂鸦狗狗后面的字母是什么 gvc显示器是什么牌子 马自达的GVC是什么? G力觉醒的马自达搭载了创驰蓝天GVC系统技术的理念是什么? 有人会看苹果手机序列号吗? C37GVCGTDP0N这是什么意思? 目前国内首款搭载创驰蓝天GVC系统技术的车型是什么 电热锅下面就是开关那个地方破了个洞,怎么办,还能用吗? 志高空气能面板说明书 chigo&#47;志高 zg-d9电热水龙头即热式快速过水加热小厨房宝电热水器怎么安装 文化课,课前的模仿操 Shannon提出的密码系统设计基本原则是什么? 学做青蛙跳鸭子走路蹲下做这3个动作中途没有休息然后过了一会我就坐在地上了坐了一会起来的时候发现自己 练习青蛙跳能提高弹跳能力吗?