2035. 分割数组的最多方案数
给你一个整数数组 nums ,其中 nums[i] 表示第 i 个袋子里的球的数目。同时给你一个整数 maxOperations 。
你可以进行如下操作至多 maxOperations 次:
- 选择任意一个袋子,并将袋子里的球分到 两个 新的袋子中,每个袋子里都有 正整数 个球。
- 比方说,一个袋子里有 5 个球,你可以把它们分到两个新袋子里,分别有 1 个和 4 个球,或者分别有 2 个和 3 个球。
你的开销是单个袋子里的球数目 最大值 ,你想要 最小化 开销。
请你返回进行上述操作后的最小开销。
解题思路
这道题可以用二分查找的方法来解决。我们可以先确定一个可能的开销 x ,然后判断是否能够在 maxOperations 次操作内,将所有袋子里的球数目都减少到不超过 x 。如果能够做到,那么说明 x 是一个可行的开销,我们可以尝试更小的 x 。如果不能做到,那么说明 x 是一个不可行的开销,我们需要尝试更大的 x 。最终我们可以找到最小的可行的开销。
具体地,我们可以用二分查找的模板来实现:
- 初始化左右边界为 1 和 max(nums) ,即最小和最大可能的开销。
- 在左右边界之间进行二分查找,对于每个中间值 x ,判断是否能够在 maxOperations 次操作内,将所有袋子里的球数目都减少到不超过 x 。这可以通过遍历数组,对于每个 nums[i] ,计算需要多少次操作才能使其不超过 x ,即 (nums[i] - 1) // x ,然后累加这些操作次数,如果总和不超过 maxOperations ,则说明可行,否则不可行。
- 如果可行,则更新右边界为 x - 1 ,否则更新左边界为 x + 1 。
- 最后返回左边界即可。
代码
class Solution:
def minimumSize(self, nums: List[int], maxOperations: int) -> int:
# 初始化左右边界
left = 1
right = max(nums)
# 在左右边界之间进行二分查找
while left <= right:
# 计算中间值
mid = (left + right) // 2
# 判断是否能够在 maxOperations 次操作内,将所有袋子里的球数目都减少到不超过 mid
ops = 0 # 记录操作次数
for num in nums:
# 计算每个袋子需要多少次操作
ops += (num - 1) // mid
# 如果操作次数超过了限制,就提前退出循环
if ops > maxOperations:
break
# 如果可行,则更新右边界
if ops <= maxOperations:
right = mid - 1
# 如果不可行,则更新左边界
else:
left = mid + 1
# 返回左边界即可
return left
2036. 移除石子使总数最小
给你一个整数数组 nums ,数组中的元素表示可以形成的最大整数。例如,如果 nums = [10, 2] ,可以形成的最大整数是 210 。
你打算从 nums 中移除 最多 一个元素,以使剩下的元素能形成一个 最小 的整数。例如,如果 nums = [1,1,1] ,可以移除任意一个元素,剩下的元素能形成的最小整数是 11 。
请你返回你能得到的 最小 的整数,并用字符串表示。
解题思路
这道题可以用贪心的方法来解决。我们可以观察到,如果要使得剩下的元素能形成一个最小的整数,那么我们应该尽可能地保留最高位上的数字,然后依次考虑次高位、次次高位等等。也就是说,我们应该从左到右遍历数组,找到第一个比它左边的数字大的数字,然后将它移除。如果没有这样的数字,说明数组是递增或者相等的,那么我们可以移除最后一个数字。
具体地,我们可以用以下步骤来实现:
- 首先,我们需要将数组中的每个数字转换为字符串,并按照字典序排序。这样可以保证数组中的每个数字在形成最大整数时都是按照它们在数组中出现的顺序排列的。
- 然后,我们从左到右遍历数组,找到第一个比它左边的数字大的数字,并记录它的索引。如果没有这样的数字,说明数组是递增或者相等的,那么我们记录最后一个数字的索引。
- 最后,我们将数组中除了记录的索引之外的所有数字拼接起来,返回结果即可。
代码
class Solution:
def removeOneDigit(self, nums: List[int]) -> str:
# 将数组中的每个数字转换为字符串,并按照字典序排序
nums = sorted(map(str, nums))
# 从左到右遍历数组,找到第一个比它左边的数字大的数字,并记录它的索引
index = -1 # 记录要移除的数字的索引
for i in range(1, len(nums)):
if nums[i] > nums[i - 1]:
index = i
break
# 如果没有这样的数字,说明数组是递增或者相等的,那么记录最后一个数字的索引
if index == -1:
index = len(nums) - 1
# 将数组中除了记录的索引之外的所有数字拼接起来,返回结果即可
ans = ""
for i in range(len(nums)):
if i != index:
ans += nums[i]
return ans