前两道都很简单暴力就能做。
5685. 交替合并字符串
class Solution {
public:
string mergeAlternately(string word1, string word2) {
string res;
int s1=word1.size();
int s2=word2.size();
int i=0;
while(i<s1&&i<s2){
res+=word1[i];
res+=word2[i];
i++;
}
for(int j=i;j<s1;j++)res+=word1[j];
for(int j=i;j<s2;j++)res+=word2[j];
return res;
}
};
5686. 移动所有球到每个盒子所需的最小操作数
class Solution {
public:
vector<int> minOperations(string boxes) {
int n=boxes.size();
vector<int>res(n);
for(int i=0;i<n;i++){
int cnt=0;
for(int j=0;j<n;j++){
if(boxes[j]=='1')cnt+=abs(j-i);
}
res[i]=cnt;
}
return res;
}
};
5687. 执行乘法运算的最大分数
给你nums数组和M数组,遍历M数组然后每次M[i]选一个nums数组左右端点其中一个相乘贡献答案(选到的就把它删去)。问选m个之后的答案的贡献最大多少。
首先这是一个区间dp问题。不过看到大佬用的记忆化搜索写的更简单。
记忆化搜索:
状态f[l][r]表示l选几个r选几个。那么res=f[0][0]。让它往下搜m层即可。这里需要注意的是n的范围1e6。而m范围1e3。相比定义状态我们不能这样定义f[l][r]表示区间[l,r]的贡献答案,那么答案就变成了f[0][n-1]。状态就变成了这样,这样数组存不下那么大的二维空间
int lvalue=dfs(cur+1,l+1,r,n,m,nums,M)+M[cur]*nums[l];
int rvalue=dfs(cur+1,l,r+1,n,m,nums,M)+M[cur]*nums[r];
因此定义第一种状态。
const int N=1e3+50;
int f[N][N];
class Solution {
public:
int dfs(int cur,int l,int r,int n,int m,vector<int>& nums, vector<int>& M)
{
if(cur>=m) return 0;
if(f[l][r]!=-1)return f[l][r];
int lvalue=dfs(cur+1,l+1,r,n,m,nums,M)+M[cur]*nums[l];
int rvalue=dfs(cur+1,l,r+1,n,m,nums,M)+M[cur]*nums[n-1-r];
f[l][r]=max(lvalue,rvalue);
return f[l][r];
}
int maximumScore(vector<int>& nums, vector<int>& M) {
memset(f,-1,sizeof f);
int n=nums.size(),m=M.size();
return dfs(0,0,0,n,m,nums,M);
}
};
5688. 由子序列构造的最长回文串的长度
给你两个串,求两个串的非空子序列合并得到一个字符串。并且该字符串是回文串,且长度最大。
首先要知道怎么求一个字符串的最长回文子序列。力扣题库就有。其次我们可以把两个字符串合并在一起。然后就变成了求合并后的最长回文子序列的长度。但是还有一个限制,要求是两个串非空。这个你只要满足i在第一个区间j在第二个区间即可。
const int N=2e3+5;
class Solution {
public:
int f[N][N];
int longestPalindrome(string word1, string word2) {
string s=word1+word2;
int len1=word1.size(),len2=word2.size(),n=s.size(),res=0;
for(int i=n-1;i>=0;i--){
f[i][i]=1;
for(int j=i+1;j<n;j++){
if(s[i]==s[j]){
f[i][j]=f[i+1][j-1]+2;
if(i<len1&&j>=len1)res=max(res,f[i][j]);
}else f[i][j]=max(f[i+1][j],f[i][j-1]);
}
}
//cout<<f[0][n-1];
return res;
}
};