最长递增子序列

来源:互联网 发布:淘宝宝贝创建时间查询 编辑:程序博客网 时间:2024/05/29 10:36

给定一个长度为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;}


0 0