LeetCode刷题day1
文章目录
LCR 095. 最长公共子序列
给定两个字符串 text1
和 text2
,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0
。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
- 例如,
"ace"
是"abcde"
的子序列,但"aec"
不是"abcde"
的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
示例 1:
输入:text1 = "abcde", text2 = "ace"
输出:3
解释:最长公共子序列是 "ace" ,它的长度为 3 。
示例 2:
输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc" ,它的长度为 3 。
示例 3:
输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0 。
提示:
1 <= text1.length, text2.length <= 1000
text1
和text2
仅由小写英文字符组成。
分析:
这是一道动态规划题,LCS,它不要求连续,只要求顺序,这有点像最长字串问题,但是,是否感觉更有意思?
s1 = "abcde", s2 = "ace"
1. 定义:D[i][j]
定义为s1前i个字符 与 s2前j个字符的LCS。
2. 分解:从最终状态往前推演。
①末尾能匹配上:D[i][j] = 1 +D[i-1][j-1]
②末尾不能匹配上: 丢掉s1
末尾:D[i][j] = D[i-1][j]
丢掉`s2`末尾:`D[i][j] = D[i][j-1] `
谁效果好留下谁。即:D[i][j] = max( D[i][j-1], D[i][j-1])
3.子问题
- D00 = 0
- D0j = 0
- Di0 =0
上代码:
class Solution {
//注意i,j对应问题
public:
int longestCommonSubsequence(string s1, string s2) {
int d[1000][1000];
for(int i=0;i<1000;i++){
for(int j=0;j<1000;j++)
d[i][j]=0;
}
int LCS=0;
for(int i=1;i<=s1.length();i++) {
for(int j=1;j<=s2.length();j++) {
if(s1[i-1]==s2[j-1]) {//i-1,j-1
d[i][j]=d[i-1][j-1]+1;
}
else {
d[i][j]= max(d[i-1][j],d[i][j-1]);
}
if(LCS<d[i][j]) {
LCS=d[i][j];
}
}
}
return LCS;//找到最大值,其实右下角,一定是最大值
}
};
416. 分割等和子集
给你一个 只包含正整数 的 非空 数组 nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。
示例 2:
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。
提示:
1 <= nums.length <= 200
1 <= nums[i] <= 100
分析:
这就是个01背包问题。
什么是01背包问题?
题解
本题就是把数组一分为二,且是均分。因此,如果数组累加和为奇数,肯定不行。注意题目的范围,注意调整。
代码:
class Solution {
public:
bool canPartition(vector<int>& nums) {
int c=0;
for (int i = 0; i < nums.size(); i++)
c+=nums[i];
if(c%2!=0)//先排除一部分
return false ;
c/=2;
int m=c+3;
int d[201][m];
for(int i=0;i<201;i++){
for(int j=0;j<m;j++)//注意界限,直接开大数组,容易超时
if(i==0||j==0)
d[i][j]=0;
}
for (int i = 1; i <= nums.size(); i++) {
for (int j = 1; j <=c ; j++) {
if(nums[i-1]>j){//can't,直接放不进去
d[i][j]=d[i-1][j];
}
else{
d[i][j]=max(nums[i-1]+d[i-1][j-nums[i-1]],d[i-1][j]);
}
}
}
for(int i=1;i<=nums.size();i++){
for(int j=1;j<=c;j++)
if(d[i][j]==c)//d[i][j]装的就是数字和,也就是value价值,就是c;通俗讲,d[i][j]求出的就是能拿进背包的数字,他们的价值=1/2全部,剩下的自然也是1/2全部
return true;
}
return false;
}
};