题目链接:300.最长递增子序列
还是分析清楚dp数组含义和递推公式的问题,第一遍没做出来这个就是因为:1.没想清楚dp数组下标含义,2。没推明白递推公式
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if(nums.size()==1) return 1;
vector<int> dp(nums.size(),1);
int result=0;
for(int i=1;i<nums.size();i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j]) dp[i]=max(dp[i],dp[j]+1);
}
result=max(result,dp[i]);
}
return result;
}
};
题目链接:674. 最长连续递增序列
太简单了,根本不需要动归,浪费空间
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
if(nums.size()==1) return 1;
int result=1,tmp=1,start=nums[0],end=nums[0];
for(int i=0;i<nums.size();i++){
if(nums[i]<=end){
start=nums[i];
end=nums[i];
tmp=1;
}
else{
end=nums[i];
tmp++;
}
result=max(result,tmp);
}
return result;
}
};
题目链接;Leetcode718. 最长重复子数组
这道题值得二刷,还是有一定难度的。
class Solution {
public:
int findLength(vector<int>& nums1, vector<int>& nums2) {
if(nums1.size()==1 || nums2.size()==1) return 1;
vector<vector<int>> dp(nums1.size(),vector<int>(nums2.size(),0));
int result=0;
for (int i = 0; i < nums1.size(); i++) if (nums1[i] == nums2[0]) dp[i][0] = 1;
for (int j = 0; j < nums2.size(); j++) if (nums1[0] == nums2[j]) dp[0][j] = 1;
for(int i=0;i<nums1.size();i++){
for(int j=0;j<nums2.size();j++){
if(i>=1 && j>=1 && nums1[i]==nums2[j]) dp[i][j]=dp[i-1][j-1]+1;
result=max(result,dp[i][j]);
}
}
return result;
}
};
题目链接:Leetcode1143. 最长公共子序列
这题复制粘贴的答案,递推公式部分没想明白。
这里有个小技巧,把dp[i][j]
定义为长度i
和长度j
使用起来更方便一些,省的初始化0那一排了。
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));
for (int i = 1; i <= text1.size(); i++) {
for (int j = 1; j <= text2.size(); j++) {
if (text1[i - 1] == text2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[text1.size()][text2.size()];
}
};
题目链接:Leetcode1035. 不相交的线
跟上道题一模一样
class Solution {
public:
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
vector<vector<int>> dp(nums1.size()+1,vector<int>(nums2.size()+1,0));
int result=0;
for(int i=1;i<=nums1.size();i++){
for(int j=1;j<=nums2.size();j++){
if(nums1[i-1]==nums2[j-1]) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
result=max(result,dp[i][j]);
}
}
return result;
}
};
题目链接:Leetcode53. 最大子数组和
用dp反而浪费,用贪心就可以了。
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size()==1) return nums[0];
vector<int> dp(nums.size(),0);
dp[0]=nums[0];
int result=dp[0];
for(int i=1;i<nums.size();i++){
if(dp[i-1]<0) dp[i]=nums[i];
else dp[i]=dp[i-1]+nums[i];
result=max(result,dp[i]);
}
return result;
}
};
题目链接:Leetcode392.判断子序列
只能说不愧是简单题,确实简单,根本用不到dp
class Solution {
public:
bool isSubsequence(string s, string t) {
int indexS=0;
for(int indexT=0;indexT<t.size();indexT++){
if(indexS==s.size()) return true;
if(s[indexS]==t[indexT]){
indexS++;
}
}
return indexS==s.size();
}
};
题目链接:Leetcode115.不同的子序列
class Solution {
public:
int numDistinct(string s, string t) {
vector<vector<uint64_t>> dp(s.size()+1,vector<uint64_t>(t.size()+1,0));
for(int i=0;i<=s.size();i++) dp[i][0]=1;
for(int i=1;i<=s.size();i++){
for(int j=1;j<=t.size();j++){
if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
else dp[i][j]=dp[i-1][j];
}
}
return dp[s.size()][t.size()];
}
};
题目链接:Leetcode647. 回文子串
转换思路,别总想着以i结尾的数量,想想以i为中心,或以i和i+1为中心
class Solution {
private:
int extend(string& s,int left,int right){
int n=s.size(),res=0;
while(left>=0 && right<n && s[left]==s[right]){
left--;
right++;
res++;
}
return res;
}
public:
int countSubstrings(string s) {
int result=0;
for(int i=0;i<s.size();i++){
result+=extend(s,i,i);//以i为中心向两边
result+=extend(s,i,i+1);//以i和i+1为中心向两边
}
return result;
}
};
题目链接:Leetcode516.最长回文子序列
class Solution {
public:
int longestPalindromeSubseq(string s) {
vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));
for (int i = 0; i < s.size(); i++) dp[i][i] = 1;
for (int i = s.size() - 1; i >= 0; i--) {
for (int j = i + 1; j < s.size(); j++) {
if (s[i] == s[j]) {
dp[i][j] = dp[i + 1][j - 1] + 2;
} else {
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
return dp[0][s.size() - 1];
}
};