Leetcode 动态规划学习总结
利用动态规划解决字串子序列问题
动态规划?
通过总结规律找出最优解决方案(数学归纳法)!!!
动态规划一般可分为线性动规,区域动规,树形动规,背包动规四类
子串和子序列的区别?
1.子串是字符串连续不断的一块字符串:例如"abcdefg" 则"bcd" 为其子串;
2.子序列中的字符都是字符串的子集,但是一定是顺序上是单调的:例如"abcdefg" 则"acfg"其子序列;
最长递增子串与最长递增子序列
最长递增子序列(Longest Increasing Subsequence,简写 LIS)是比较经典的一个问题,比较容易想到的是动态规划解法,时间复杂度 O(N^2),我们借这个问题来由浅入深讲解如何写动态规划。比较难想到的是利用二分查找,时间复杂度是 O(NlogN),
动态规划:DP[i] = fmax(RES, DP[i - 1] + 1)
C++:
int longestSubString(std::vector<int> s)
{
std::vector<int> dp(s.size(), 0);
dp[0] = 1;
for (int i = 1; i < s.size(); ++i)
{
for(int j = 0; j < i; j++)
{
if(s[i] > s[j])
dp[i] = fmax(dp[i], dp[j] + 1);
}
}
return *max_element(dp.begin(), dp.end());
}
最长递增子串
解题思路:dp[i]:表示第i个元素,它的递增元素的个数。比如[1,3,5 ]元素3 从1递增到3 递增元素个数是2,dp[1]=2, dp=[1]*n
int findLengthOfLCIS(vector<int>& nums) {
int length = nums.size();
if(!length)
return 0;
vector<int> dp(length, 1);
int res = 1;
for(int i = 1; i < length; i++)
{
if(nums[i - 1] < nums[i])
dp[i] = dp[i - 1] + 1;
res = fmax(dp[i], res);
}
return res;
}
(2)滑动窗口
算法:
每个(连续)增加的子序列是不相交的,并且每当 nums[i-1]>=nums[i] 时,每个此类子序列的边界都会出现。当它这样做时,它标志着在 nums[i] 处开始一个新的递增子序列,我们将这样的 i 存储在变量 anchor 中。
例如,如果 nums=[7,8,9,1,2,3],那么 anchor 从 0 开始(nums[anchor]=7),并再次设置为 anchor=3(nums[anchor]=1)。无论 anchor 的值如何,我们都会记录 i-anchor+1 的候选答案、子数组 nums[anchor]、nums[anchor+1]、…、nums[i] 的长度,并且我们的答案会得到适当的更新。
int findLengthOfLCIS(vector<int>& nums) {
int pos = 0, res = 0;
int length = nums.size();
for(int i = 0; i < length; i++)
{
if(i > 0 && nums[i - 1