2861. 最大合金数
class Solution:
def maxNumberOfAlloys(self, n: int, k: int, budget: int, composition: List[List[int]], stock: List[int], cost: List[int]) -> int:
res = 0
left = 0
right = min(stock) + budget
while left <= right:
mid = (left + right) // 2
valid = False
for i in range(k): # 遍历 机器
spend = 0 # 计算 该机器的 生产 mid 个 合金 的 花费
for composition_j, stock_j, cost_j in zip(composition[i], stock, cost):
spend += max(composition_j * mid - stock_j, 0)* cost_j
if spend <= budget:
valid = True
break
if valid:
res = mid
left = mid + 1
else:
right = mid - 1
return res
class Solution {
public:
int maxNumberOfAlloys(int n, int k, int budget, vector<vector<int>>& composition, vector<int>& stock, vector<int>& cost) {
int res = 0;
int left = 0, right = 2e8;
while (left <= right){
int mid = (left + right) / 2;
bool valid = false;
for (int i = 0; i < k; ++i){// k 台机器
long long spend = 0;
for (int j = 0; j < n; ++j){// n 种 合金
spend += max((long long)(composition[i][j]) * mid - stock[j], 0LL) * cost[j];
}
if (spend <= budget){
valid = true;
break;
}
}
if (valid){
res = mid;
left = mid + 1;
}else{
right = mid - 1;
}
}
return res;
}
};
2731. 移动机器人
这里 要用 一个两两距离和求解公式, 否则超时
此外, 碰撞可忽略。
class Solution:
def sumDistance(self, nums: List[int], s: str, d: int) -> int:
#
for i, c in enumerate(s):
nums[i] += d if c == 'R' else -d
res = 0
nums.sort()
n = len(nums)
return sum([(nums[i] - nums[i - 1]) * i * (n - i) for i in range(1, n)]) % (10**9 + 7)
class Solution {
public:
int sumDistance(vector<int>& nums, string s, int d) {
int n = nums.size();
const int MOD = 1e9 + 7;
vector<long long> arr(n);
for (int i = 0; i < n; ++i){
arr[i] = 1LL * nums[i] + (s[i] == 'L' ? -d : d);
}
sort(arr.begin(), arr.end());
long long res = 0;
for (int i = 1; i < n; ++i){
res += i * (arr[i] - arr[i - 1]) % MOD * (n - i) % MOD;
res %= MOD; // (ab)% MOD = (a % MOD)(b % MOD) % MOD
}
return res;
}
};
2272. 最大波动的子字符串
class Solution:
def largestVariance(self, s: str) -> int:
# diff 维护 a 和 b 出现次数 之差 不一定包含 b
# diffWithB
res = 0
for a, b in permutations(ascii_lowercase, 2):
diff, diffWithB = 0, -inf
for ch in s:
if ch == a:
diff += 1
diffWithB += 1
elif ch == b:
diff -= 1
diffWithB = diff # 此时 肯定包含 b
if diff < 0:
diff = 0
if diffWithB > res:
res = diffWithB
return res
class Solution:
def largestVariance(self, s: str) -> int:
# 假设 a 多 b 少 。 最理想的子串情况 是 尽量多的 a 和 1个 b
# diff 记录 只含a 的未包含 b 的子串长度。
# diffWithB 出现 一个b 了。 aab a***a**aab 等的 差
## 优化, a 只考虑 s 中 出现的
res = 0
diff = [[0] * 26 for _ in range(26)]
diffWithB = [[-inf] * 26 for _ in range(26)]
for ch in s:
ch = ord(ch) - ord('a')
for i in range(26):
if i == ch:
continue
diff[ch][i] += 1
diffWithB[ch][i] += 1 # 碰到 b 也要 维护, 有时更长
diff[i][ch] -= 1
diffWithB[i][ch] = diff[i][ch]
if diff[i][ch] < 0:
diff[i][ch] = 0
res = max(res, diffWithB[ch][i], diffWithB[i][ch])
return res
——————————
⭐ 方法:枚举最多和最少的字符 + 最大子段和动态规划
class Solution:
def largestVariance(self, s: str) -> int:
pos = defaultdict(list)
for i, ch in enumerate(s):
pos[ch].append(i)
res = 0
for c0, pos0 in pos.items():
for c1, pos1 in pos.items():
if c0 != c1:
i = j = 0
f, g = 0, -inf
while i < len(pos0) or j < len(pos1):
if j == len(pos1) or (i < len(pos0) and pos0[i] < pos1[j]):
f += 1
g += 1
i += 1
else:
f = f - 1
g = f
f = max(f, 0) # 被 b 隔断了
j += 1
res = max(res, g)
return res
class Solution {
public:
int largestVariance(string s) {
unordered_map<char, vector<int>> pos;
for (int i = 0; i < s.size(); ++i){
pos[s[i]].emplace_back(i);
}
int res = 0;
for (auto && [c0, pos0] : pos){
for (auto && [c1, pos1] : pos){
if (c0 != c1){
int i = 0, j = 0;
int f = 0, g = INT_MIN;
while (i < pos0.size() || j < pos1.size()){
if (j == pos1.size() || (i < pos0.size() && pos0[i] < pos1[j])){
++f;
++g;
++i;
}else{
--f;
g = f;
f = max(f, 0); // 被 截断了,
++j;
}
res = max(res, g);
}
}
}
}
return res;
}
};