子序列问题
- 删除一次得到的最大和
- 最大子数组和
- 最长公共子序列:
- 最长上升子序列(要输出序列,和最大长度)
-
- 导弹拦截 (最长上升/下降子序列长度)
删除一次得到的最大和
class Solution {
public:
int maximumSum(vector<int>& arr) {
int n=arr.size();
vector<int> left(n),right(n);
left[0]=arr[0],right[n-1]=arr[n-1];
int ans=left[0];
for(int i=1;i<n;i++)
{
left[i]=max(left[i-1],0)+arr[i];
right[n-i-1]=max(right[n-i],0)+arr[n-i-1];
ans=max(ans,left[i]);
}
for(int i=1;i<n-1;i++)
ans=max(ans,left[i-1]+right[i+1]);
return ans;
}
};
最大子数组和
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n=nums.size();
vector<int> dp(n,0);
dp[0]=nums[0];
for(int i=1;i<n;i++)
{
if(dp[i-1]>0)
dp[i]=dp[i-1]+nums[i];
else
dp[i]=nums[i];
}
return *max_element(dp.begin(),dp.end());
}
};
最长公共子序列:
class Solution {
public:
int cache[1005][1005];
int dfs(string& s, string& t, int i, int j)
{
if (i < 0 || j < 0)return 0;
int& ans = cache[i][j];
if (ans != 0)return ans;
if (s[i] == t[j])
return ans = dfs(s, t, i - 1, j - 1) + 1;
else
return ans = max(dfs(s, t, i - 1, j), dfs(s, t, i, j - 1));
}
int longestCommonSubsequence(string s, string t) {
return dfs(s, t, s.size() - 1, t.size() - 1);
}
};
最长上升子序列(要输出序列,和最大长度)
两种解法:
1.dp
#include
using namespace std;
int n, a[201], dp[201], pre[201];
void reverse_print(int index)
{
if (index == -1)return;
reverse_print(pre[index]);
cout << a[index] << " ";
}
int main()
{
memset(pre, -1, sizeof(pre));
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i];
dp[i] = 1;
}
int maxx = 1;
int maxIndex = 0;
for (int i = 1; i < n; i++)
{
for (int j = 0; j < i; j++)
{
if (a[i] >= a[j])
{
if (dp[j] + 1 > dp[i])
{
dp[i] = dp[j] + 1;
pre[i] = j;
}
}
if (dp[i] > maxx)
{
maxx = dp[i];
maxIndex = i;
}
}
}
std::cout << "max=" << maxx << endl;
reverse_print(maxIndex);
return 0;
}
2.贪心+二分
class Solution {
public:
int low_bound(vector<int>& arr, int key)
{
int left = 0, right = arr.size();
while (left < right)
{
int mid = (left + right) / 2;
if (arr[mid] < key)
left = mid + 1;
else if (arr[mid] > key)
right = mid;
}
return right;
}
int lengthOfLIS(vector<int>& nums) {
vector<int> ret;
ret.push_back(nums[0]);
for (int i = 1, k = 1; i < nums.size(); i++)
{
if (nums[i] > ret[k - 1])
{
ret.push_back(nums[i]);
k++;
}
else if (nums[i] < ret[k - 1])
{
int pos = low_bound(ret, nums[i]);
ret[pos] = nums[i];
}
}
return ret.size();
}
};
导弹拦截 (最长上升/下降子序列长度)
#include
using namespace std;
int n = 1, a[1001], dp_up[1001], dp_down[1001];
int main()
{
while (cin >> a[n])
{
dp_up[n] = dp_down[n] = 1;
n++;
}
n--;
int max_down = 1, max_up = 1;
for (int i = 2; i <= n; i++)
{
for (int j = 1; j < i; j++)
{
if (a[i] > a[j])dp_up[i] = max(dp_up[i], dp_up[j] + 1);
if (a[i] <= a[j])dp_down[i] = max(dp_down[i], dp_down[j] + 1);
}
max_down = max(max_down, dp_down[i]);
max_up = max(max_up, dp_up[i]);
}
cout << max_down << endl << max_up << endl;
return 0;
}