最长递增子序列

本文介绍了一种求解最长递增子序列的有效算法。利用动态规划思想,定义dp[i]为以第i个元素结尾的最长递增子序列长度,并通过二分查找优化过程,实现了高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一个长度为N的数组a0,a1,a2...,an-1,找出一个最长的单调递增子序列(注:递增的意思是对于任意的i<j,都满足ai<aj,此外子序列的意思是不要求连续,顺序不乱即可)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4。

提示:一种解法是转换为最长公共子序列问题,另外一种解法则是动态规划。当我们考虑动态规划解决时,可以定义dp[i]为以ai为末尾的最长递增子序列的长度,故以ai结尾的递增子序列

  • 要么是只包含ai的子序列
  • 要么是在满足j<i并且aj<ai的以ai为结尾的递增子序列末尾,追加上ai后得到的子序列

如此,便可建立递推关系,在O(N^2)时间内解决这个问题。

int binFind(int* arr, int len, int goal) {
	int low = 0;
	int high = len - 1;
	while (low <= high) {
		int mid = (low + high) >> 1;
		if (arr[mid] == goal) {
			return mid;
		} else if (arr[mid] < goal) {
			low = mid + 1;
		} else {
			high = mid - 1;
		}
	}
	return low;
}

stack<int> findLongestSubquence(int* arr, int len) {
	stack<int> result;
	if (!arr || !len) {
		return result;
	}
	int* dp = new int[len];
	memset(dp, 0, len * sizeof(int));
	int* tmp = new int[len];
	memset(tmp, 0, sizeof(int) * len);

	dp[0] = 1;
	tmp[0] = arr[0];
	int curLen = 1;
	for (int i = 1; i < len; ++i) {
		int index = binFind(tmp, curLen, arr[i]);
		if (index == curLen) {
			curLen++;
		}
		tmp[index] = arr[i];
		dp[i] = index + 1;
	}

	for (int i = len; i >= 0; --i) {
		if (dp[i] == curLen) {
			result.push(arr[i]);
			curLen--;
			if (!curLen) {
				break;
			}
		}
	}
	delete dp;
	delete tmp;
	return result;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值