最长上升子序列问题,有一个正整数数列,长度n在1000之内,元素a[i]在10^5之内,求最长递增子序列的长度。
这里,时间复杂度是O(n^2);在递归与分治法过后,是不是发现了问题的端倪呢?到这里,我们就可以很方便地转化成动态规划的问题了。形式有两种,读者可以自己去实现:1)dp[i]:以a[i]开始的最长递增子序列的长度;2)dp[i] 以a[i]结尾的最长递增子序列的长度
class Solution { public: bool wordBreak(string s, unordered_set<string> &dict) { int n=s.size(); if(n==0) return true; bool dp[n+1]; fill(dp, dp+n+1, false); dp[0]=true; int i, j; for (i = 0; i < n; ++i){ for(j=i;j>=0;j--){ if(dp[j]){ if( dict.find(s.substr(j, i+1 - j)) != dict.end() ){ dp[i+1]=true; break; } } } } return dp[n]; } };进一步的分析:如果有这样的一个例子,s="aaaaaaaaaaaaaaa...a"(100个a);同样dict里面的元素就是s,这样,这个时间复杂度依然是O(n^2),而实际上,dp[0]~dp[n-1]的结果都为0.在计算dp[i]的时候,我们的时间复杂度也是O(n), 这个时间复杂度可以减小为O(dict.size()). 另一方面,我们采用了线性查找来确定d[j]为true,实际上,我们可以采用堆栈来存储dp[j]为true对应的j,这也能在一定程度上减小时间复杂度。
原文地址:http://blog.csdn.net/trochiluses/article/details/38017007