LC 2513. 最小化两个数组中的最大值
https://leetcode.cn/problems/minimize-the-maximum-of-two-arrays/
这题初看起来不怎么难,但是可让我想了好长时间,把这个思路理顺了之后就还好。可见清晰通畅的思路是多么地重要,即使知道框架但是没有清晰的思路,写起来也会是相当纠结的。
这题总体的框架就是二分,二分的上限是 `2*(uniqueCount1 + uniqueCount2)` 因为divisor最小就是2,如果两个divisor都是2的话,那么只需要取所有的奇数就行。
主体就是怎么写这个二分,假设最大的数是k:
- 那么可以同时被group1/2使用的数量是 `a = k - k / divisor1 - k / divisor2 + k / lcm`
- 只能被group1使用的数量则是 `b = (k - k / divisor1) - a`
- 只能被group2使用的数量则是 `c = (k - k / divisor1) - a`
- 分配的时候我们优先满足group1, 并且优先使用 "只能被group1使用的数",如果不满足条件就返回false: `(b + a) < uniqueCount1`
- 剩余的数量在和 "只能被group2使用的数" 累加,如果不满足条件就返回false。
- 注意这里剩余的数量中,我们只能选择 "可以同时被group1/2使用的数": `min(a, (b+a) - uniqueCount1) + c < uniqueCount2`
class Solution:
def minimizeSet(self, divisor1: int, divisor2: int, uniqueCnt1: int, uniqueCnt2: int) -> int:
def GCD(a, b):
while b != 0:
a, b = b, a % b
return a
def LCM(a, b):
return a * b // GCD(a, b)
def test(k):
lcm = LCM(divisor1, divisor2)
# be used to g1 and g2 both
a = k - k // divisor1 - k // divisor2 + k // lcm
# only to g1
b = (k - k // divisor1) - a
# only to g2
c = (k - k // divisor2) - a
if (b + a) < uniqueCnt1: return False
r = min(a, (b + a) - uniqueCnt1)
if (r + c) < uniqueCnt2: return False
return True
s, e = 1, (uniqueCnt1 + uniqueCnt2) * 2
while s <= e:
m = (s + e) // 2
if test(m):
e = m - 1
else:
s = m + 1
return s