我的第四次LeetCode周赛
心情
题目在此
这次真的非常巴适,第一次AK,主要是题目比较简单😁
第一题(检查字符串是否为数组前缀)
判断一个字符串是否是另一个前缀字符串
错了一次
“a”
[“aa”,“aaa”,“aaaa”]
这种是错误的,我的代码一开始没考虑到这个。
class Solution {
public:
bool isPrefixString(string s, vector<string>& words) {
int n = words.size(),l = s.size();
int k = 0;
for (int i = 0; i < n; i ++){
int m = words[i].size();
for (int j = 0; j < m; j ++){
if (s[k++]!=words[i][j])return false;
//if (k == l)return true; 错一发就是这里
}
if (k == l)return true;
}
return false;
}
};
第二题(移除石子使总数最小)
把一个数组最大的元素除2向上取整,进行k次操作。
用一个priority_queue 把数组放到优先队列直接操作。
class Solution {
public:
int minStoneSum(vector<int>& p, int k) {
priority_queue<int> q;
int le = p.size();
for (int i = 0; i < le; i ++)q.push(p[i]);
while(k--){
int t = (q.top()+1)/2;
q.pop();
q.push(t);
}
int res = 0;
while(q.size()){
res += q.top();
q.pop();
}
return res;
}
};
第三题(使字符串平衡的最小交换次数)
一个类似"] ] ] [ [ ["这样的字符串,一次操作将两个字符进行交换,求最小的操作次数,使得字符串合法
“] ] ] [ [ [”
2次操作
[ [ ][ ] ]
多找几个样例,可以发现数出向左违规的字符数量,最小的操作次数为:(向左违规的字符数量+1)/2
class Solution {
public:
int minSwaps(string s) {
int n = s.size();
int l = 0,r = 0;
int res = 0;
for (int i = 0; i < n; i ++){
if (s[i]=='[')r++;
if (s[i]==']')l++;
if (l > r){
res++;
l --;
}
}
return (res+1)/2;
}
};
第四题(找出到每个位置为止最长的有效障碍赛跑路线)
抽解题意:就是计算一个字符串第i个字符为结尾的最长上升子序列的长度,并且这个字符串必须包括第i个字符的最大长度。
解法:用最长上升子序列用二分优化模板题
class Solution {
public:
vector<int> longestObstacleCourseAtEachPosition(vector<int>& o) {
int n = o.size();
vector<int> q(n+1);
vector<int> vt;
int len = 0;
for (int i = 0; i < n; i ++){
int l = 0,r = len;
while (l < r){
int mid = l + r + 1 >> 1;
if (q[mid] <= o[i])l = mid;
else r = mid - 1;
}
len = max(len,r + 1);
vt.push_back(r+1);
q[r + 1] = o[i];
}
return vt;
}
};
最长上升子序列(模板)
-
普通版O(N^2)
#include <bits/stdc++.h> using namespace std; int n,a[1010],f[1010]; //f[i]表示以a[i]结尾的最长子序列长度 int main(){ cin >> n; for(int i = 1; i <= n; i++)cin >> a[i]; for(int i = 1; i <= n; i++){ f[i] = 1; //f[i]最小为1 for(int j = 1; j < i; j ++) if(a[j] < a[i]) //更新 f[i] = max(f[i],f[j]+1); } int ans = 0; for(int i = 1; i <= n; i++)ans = max(ans,f[i]); //最后寻找最大值 cout << ans << endl; return 0; }
-
优化版O(NlogN):是从上面动态规划推到出来的,但是又有些像贪心
#include <bits/stdc++.h> using namespace std; const int N = 100010; int n,a[N],q[N]; int main() { scanf("%d", &n); for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]); int len = 0; for (int i = 0; i < n; i ++ ){ int l = 0, r = len; //二分比当前数小的最大的一个数 while (l < r){ int mid = l + r + 1 >> 1; if (q[mid] < a[i]) l = mid; else r = mid - 1; } len = max(len, r + 1); //计算长度 q[r + 1] = a[i]; //替换 } printf("%d\n", len); return 0; }