第 80 场双周赛
Problem A - 强密码检验器 II
方法一:模拟
- 时间复杂度 。
- 空间复杂度 。
参考代码(Python 3)
special_set = set("!@#$%^&*()-+")
class Solution:
def strongPasswordCheckerII(self, password: str) -> bool:
n = len(password)
if n < 8:
return False
lower = False
upper = False
digit = False
special = False
for i, p in enumerate(password):
if i > 0 and p == password[i - 1]:
return False
if 'a' <= p <= 'z':
lower = True
elif 'A' <= p <= 'Z':
upper = True
elif '0' <= p <= '9':
digit = True
elif p in special_set:
special = True
return lower and upper and digit and special
Problem B - 咒语和药水的成功对数
方法一:排序 + 双指针
- 时间复杂度 。
- 空间复杂度 。
参考代码(C++)
class Solution {
public:
vector<int> successfulPairs(vector<int>& spells, vector<int>& potions, long long success) {
int n = spells.size(), m = potions.size();
sort(potions.begin(), potions.end());
vector<int> order(n);
for (int i = 0; i < n; ++i)
order[i] = i;
sort(order.begin(), order.end(), [&](int i, int j){
return spells[i] < spells[j];
});
vector<int> ans(n);
int ptr = m;
for (int i : order) {
while (ptr >= 1 && 1LL * spells[i] * potions[ptr - 1] >= success)
ptr--;
ans[i] = m - ptr;
}
return ans;
}
};
Problem C - 替换字符后匹配
方法一:暴力
- 时间复杂度 。
- 空间复杂度 。
参考代码(Rust)
impl Solution {
pub fn match_replacement(s: String, sub: String, mappings: Vec<Vec<char>>) -> bool {
let mut adj = vec![vec![false; 256]; 256];
for mapping in mappings {
adj[mapping[0] as u8 as usize][mapping[1] as u8 as usize] = true;
}
let s = s.chars().collect::<Vec<_>>();
let sub = sub.chars().collect::<Vec<_>>();
let n = s.len();
let m = sub.len();
for i in 0..n - m + 1 {
let mut can = true;
for j in 0..m {
if s[i + j] == sub[j] {
continue;
}
if !adj[sub[j] as u8 as usize][s[i + j] as u8 as usize] {
can = false;
break;
}
}
if can {
return true;
}
}
false
}
}
Problem D - 统计得分小于 K 的子数组数目
方法一:前缀和 + 二分
- 时间复杂度 。
- 空间复杂度 。
参考代码(C++)
class Solution {
public:
long long countSubarrays(vector<int>& nums, long long k) {
long long ans = 0;
int n = nums.size();
vector<long long> pre(n + 1);
for (int i = 1; i <= n; ++i)
pre[i] = pre[i - 1] + nums[i - 1];
for (int i = 0; i < n; ++i) {
int lo = i, hi = n - 1;
while (lo <= hi) {
int mid = (lo + hi) >> 1;
long long sum = 1LL * (mid - i + 1) * (pre[mid + 1] - pre[i]);
if (sum >= k)
hi = mid - 1;
else
lo = mid + 1;
}
ans += hi - i + 1;
}
return ans;
}
};
方法二:双指针
- 时间复杂度 。
- 空间复杂度 。
参考代码(C++)
class Solution {
public:
long long countSubarrays(vector<int>& nums, long long k) {
long long ans = 0, sum = 0;
int n = nums.size();
int l = 0;
for (int r = 0; r < n; ++r) {
sum += nums[r];
while (sum * (r - l + 1) >= k)
sum -= nums[l++];
ans += r - l + 1;
}
return ans;
}
};