LeetCode第 285 場周賽題解
阿新 • • 發佈:2022-03-20
6027. 統計陣列中峰和谷的數量
題目描述:給你一個數組nums
,統計山峰和山谷的數量,山峰山谷的定義見題目
思路:資料範圍不大,根據題意暴力模擬即可,若資料範圍很大,則將相鄰且相等的元素刪除其一,對於刪除後的陣列,可以\(O(n)\)求解
時間複雜度:\(O(n^2)\)
參考程式碼:
class Solution { public: int countHillValley(vector<int>& nums) { int res = 0, n = nums.size(); vector<int>vis(n + 1 , false); for(int i = 1 ; i < n - 1 ; ++i){ int lr = -1; for(int j = i - 1 ; j >= 0 ;--j){ if(nums[j] == nums[i]) continue; lr = nums[j]; break; } if(lr == -1) continue; int rs = -1; for(int j = i + 1 ; j < n ; ++j){ if(nums[j] == nums[i]) continue; rs = nums[j]; break; } if(rs == -1) continue; if(lr > nums[i] && rs > nums[i]){ ++res; vis[i] = true; if(vis[i - 1] == true && nums[i - 1] == nums[i]) --res; } else if(lr < nums[i] && rs < nums[i]){ ++res; vis[i] = true; if(vis[i - 1] == true && nums[i - 1] == nums[i]) --res; } } return res; } };
\(O(n)\)解法:
class Solution { public: int countHillValley(vector<int>& nums) { deque<int>q; for(auto& num : nums){ if(q.empty())q.push_back(num); else if(q.back() == num) continue; else q.push_back(num); } nums.clear(); while(!q.empty()){ nums.push_back(q.front()); q.pop_front(); } int res = 0 , n = nums.size(); for(int i = 1 ; i < n - 1 ; ++i){ if(nums[i] < nums[i - 1] && nums[i] < nums[i + 1]) ++res; if(nums[i] > nums[i - 1] && nums[i] > nums[i + 1]) ++res; } return res; } };
6028. 統計道路上的碰撞次數
題目描述:給你一個長度為\(n\)的字串s
表示n
輛車的狀態,R
表示向右行駛,L
表示向左行駛,S
表示不動。若兩輛相對行駛的車相撞積兩分,若一個行駛的車撞上了一個靜止的車積一分,兩輛車相撞之後就會保持靜止。問最終積分是多少。
思路:根據題意模擬即可
時間複雜度:\(O(n)\)
參考程式碼:
class Solution { public: int countCollisions(string s) { int res = 0; int cntlr = 0 , cntrs = 0, stop = 0; for(auto& c : s){ if(c == 'S'){ res += cntrs; cntrs = 0; stop = 1; } else if(c == 'L'){ if(cntrs){ res += cntrs + 1; cntrs = 0; stop = 1; } else if(stop) res++; } else ++cntrs; } return res; } };
6029. 射箭比賽中的最大得分
題目描述:兩個人比賽射箭,假定這兩個人用A
和B
表示,他們都射n
支箭,靶總共有12
個區域,分別表示0 , 1 , ... , 11
分,對於同一分數區域,只有當B
射在該區域的箭的數量多於A
射在該區域的箭的數量時,B
才可以獲得該區域所代表的分數,問B
最多能獲得多少分。
思路:考慮到總共只有12
個區域,所以我們列舉B
勝利的區域,然後檢驗所用箭的數量是否超過閾值即可。注意B
使用的箭的總數量與A
使用的箭的總數量必須相等。
時間複雜度:\(O(12 * 2 ^{12})\)
參考程式碼:
class Solution {
public:
vector<int> maximumBobPoints(int numArrows, vector<int>& a) {
vector<bool>vis(12 , 0);
vector<int>res;
int mx = 0;
auto dfs = [&](auto&& dfs , int cur)->void{
if(cur == 12){
int cnt = 0, sum = 0;
vector<int>ans(12 , 0);
for(int i = 0 ; i < 12 ; ++i){
if(vis[i] == false) continue;
ans[i] = a[i] + 1;
cnt += a[i] + 1;
sum += i;
}
if(cnt > numArrows) return ;
if(sum <= mx) return ;
ans[0] += numArrows - cnt;
mx = sum;
res = ans;
return ;
}
dfs(dfs , cur + 1);
vis[cur] = true;
dfs(dfs , cur + 1);
vis[cur] = false;
};
dfs(dfs , 0);
return res;
}
};
6030. 由單個字元重複的最長子字串
題目描述:給你一個長度為n
的字串s
,在給你q
個詢問,每次詢問修改某處字元為給定字元,問每次修改後字串s
中由單個字元重複組成的最長子字串的長度。
思路:比較明顯可以使用線段樹,維護最長字串。同時維護區間的字首最長,字尾最長,區間最長,最前面的數的值,最後面的數的值這5
個資訊,然後單點修改即可,每次詢問的答案就是tree[1].mx
。
時間複雜度:\(O(nlogn + qlogn)\)
參考程式碼:
class Solution {
private:
struct SegTree {
int lr, rs, mid;
int val, pre, nxt, mx, preval, nxtval;
};
vector<SegTree> tree;
void pushUp(int rt) {
tree[rt].mx = max(tree[rt << 1].mx, tree[rt << 1 | 1].mx);
if (tree[rt << 1].nxtval == tree[rt << 1 | 1].preval) {
int len = tree[rt << 1].nxt + tree[rt << 1 | 1].pre;
tree[rt].mx = max(tree[rt].mx, len);
}
tree[rt].pre = tree[rt << 1].pre;
tree[rt].nxt = tree[rt << 1 | 1].nxt;
tree[rt].preval = tree[rt << 1].preval;
tree[rt].nxtval = tree[rt << 1 | 1].nxtval;
if (tree[rt].pre == tree[rt << 1].rs - tree[rt << 1].lr + 1) {
if (tree[rt << 1].nxtval == tree[rt << 1 | 1].preval) tree[rt].pre += tree[rt << 1 | 1].pre;
else;
}
if (tree[rt].nxt == tree[rt << 1 | 1].rs - tree[rt << 1 | 1].lr + 1) {
if (tree[rt << 1].nxtval == tree[rt << 1 | 1].preval) tree[rt].nxt += tree[rt << 1].nxt;
else;
}
return;
}
void buildTree(string& s, int rt, int lr, int rs) {
tree[rt].lr = lr; tree[rt].rs = rs; tree[rt].mx = 0;
if (lr == rs) {
tree[rt].val = s[lr - 1] - 'a' + 1;
tree[rt].mx = 1;
tree[rt].preval = tree[rt].nxtval = tree[rt].val;
tree[rt].pre = tree[rt].nxt = 1;
return;
}
int mid = tree[rt].mid = lr + rs >> 1;
buildTree(s, rt << 1, lr, mid);
buildTree(s, rt << 1 | 1, mid + 1, rs);
pushUp(rt);
return;
}
void update(int rt, int pos , int val) {
if (tree[rt].lr > pos || tree[rt].rs < pos) return;
if (tree[rt].lr == tree[rt].rs) {
tree[rt].val = val;
tree[rt].preval = val;
tree[rt].nxtval = val;
return;
}
if (tree[rt].mid >= pos) update(rt << 1, pos, val);
else update(rt << 1 | 1, pos, val);
pushUp(rt);
return;
}
public:
vector<int> longestRepeating(string s, string queryCharacters, vector<int>& queryIndices) {
int n = s.size();
tree = vector<SegTree>(n + 5 << 2);
buildTree(s, 1, 1, n);
int m = queryCharacters.size();
vector<int>res(m , 0);
for (int i = 0; i < m; ++i) {
int pos = queryIndices[i] + 1, val = queryCharacters[i] - 'a' + 1;
update(1, pos, val);
res[i] = tree[1].mx;
}
return res;
}
};