这是我参与更文挑战的第20天,活动详情查看:更文挑战
1898. 可移除字符的最大数目
其实最后还是没找出错误,希望万能的掘友帮我看下
代码如下(我觉得问题大概率是check函数)
class Solution {
public:
bool arr[100007] = {false};
int maximumRemovals(string s, string p, vector<int>& removable) {
int left = 0, right = removable.size() - 1;
int mid = 0;
while(left < right){
mid = (left + right)/2 + 1;
if(check(s, p, mid, removable)){
left = mid;
}else{
right = mid - 1;
}
}
// cout << removable.size() << endl;
// printf("left:%d , right: %d, mid: %d \n",left,right,mid);
if(left == right && left == 0){
return check(s, p, 0, removable) ? 1 : 0;
}
if(left == right && right == removable.size() - 1){
return check(s, p, right, removable) ? right + 1 :right;
}
return left + 1;
}
bool check(string s, string p, int k, vector<int>& removable){
for(int i = 0; i <= k; i++){
arr[removable[i]] = true;
}
for(int i = k + 1; i < removable.size(); i ++){
arr[removable[i]] = false;
}
int j = 0;
for(int i = 0; i < p.size(); i ++){
while(j < s.size() && (s[j] != p[i] || arr[j] == true)) j++;
if(j == s.size()){
return false;
}
}
return true;
}
};
1900. 最佳运动员的比拼回合
这道题说实话很难想到是动态规划,因为大量的条件(过深的维度)让人很难发现这是一道动态规划题, 这道题就是通过每次比赛来减少参赛人数,算出最强两者相遇的回合数。
由于除最强两者以外,不同的比赛胜负结果会产生不同的回合数,因此,为了计算出最少回合数和最多回合数,我们必须分类讨论
而这,就是动态规划的状态转移方程所要操作的地方。
- 首先,我们知道互换最强两者的位置并不会得到不同的结果,
- 其次,我们知道逆序该队列也不会影响最后的结果。
因此我们可以假定,两个最强者f和s,f在队列的左侧,s在f的后面(无论fs如何分布,都可以通过逆序与互换操作得到该结果)
那么分类讨论的条件就变为了s到底是在左侧,还是在中间还是在右侧。
假定f前面减少了i个元素,n个元素最少回合数:dp1[n,f,s],n个元素最多回合数,dp2[n,f,s]
- s如果在左侧,那么f与s之间可能少了j个元素,则dp1[n,f,s]= dp1[n1,f - i, s - i - j] + 1 ; dp2[n,f,s] = dp2[n1,f - i, s - i - j] + 1
- s如果在中间,那其实和在左侧是没有区别的。
- s如果在右边,
-
- s和f如果是恰好相对,则dp1[n,f,s] = 1
- 如果s对应的s'在f左边,那么可以使用逆序,再重新计算
- 如果s对应的s'在f右边,那么可以设置j的范围为[s-n/2-i,n-s-f]之间,计算最小/最大值。