LeetCode 题解工作台
通过操作使数组长度最小
给你一个下标从 0 开始的整数数组 nums ,它只包含 正 整数。 你的任务是通过进行以下操作 任意次 (可以是 0 次) 最小化 nums 的长度: 在 nums 中选择 两个不同 的下标 i 和 j ,满足 nums[i] > 0 且 nums[j] > 0 。 将结果 nums[i] % n…
4
题型
5
代码语言
3
相关题
当前训练重点
中等 · 贪心·invariant
答案摘要
我们不妨记数组 的最小的元素为 。 如果 只出现一次,那么我们将 与数组 的其他元素进行操作,可以将其他元素全部消去,最终剩下 一个元素,答案为 。
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 贪心·invariant 题型思路
题目描述
给你一个下标从 0 开始的整数数组 nums ,它只包含 正 整数。
你的任务是通过进行以下操作 任意次 (可以是 0 次) 最小化 nums 的长度:
- 在
nums中选择 两个不同 的下标i和j,满足nums[i] > 0且nums[j] > 0。 - 将结果
nums[i] % nums[j]插入nums的结尾。 - 将
nums中下标为i和j的元素删除。
请你返回一个整数,它表示进行任意次操作以后 nums 的 最小长度 。
示例 1:
输入:nums = [1,4,3,1] 输出:1 解释:使数组长度最小的一种方法是: 操作 1 :选择下标 2 和 1 ,插入 nums[2] % nums[1] 到数组末尾,得到 [1,4,3,1,3] ,然后删除下标为 2 和 1 的元素。 nums 变为 [1,1,3] 。 操作 2 :选择下标 1 和 2 ,插入 nums[1] % nums[2] 到数组末尾,得到 [1,1,3,1] ,然后删除下标为 1 和 2 的元素。 nums 变为 [1,1] 。 操作 3 :选择下标 1 和 0 ,插入 nums[1] % nums[0] 到数组末尾,得到 [1,1,0] ,然后删除下标为 1 和 0 的元素。 nums 变为 [0] 。 nums 的长度无法进一步减小,所以答案为 1 。 1 是可以得到的最小长度。
示例 2:
输入:nums = [5,5,5,10,5] 输出:2 解释:使数组长度最小的一种方法是: 操作 1 :选择下标 0 和 3 ,插入 nums[0] % nums[3] 到数组末尾,得到 [5,5,5,10,5,5] ,然后删除下标为 0 和 3 的元素。 nums 变为 [5,5,5,5] 。 操作 2 :选择下标 2 和 3 ,插入 nums[2] % nums[3] 到数组末尾,得到 [5,5,5,5,0] ,然后删除下标为 2 和 3 的元素。 nums 变为 [5,5,0] 。 操作 3 :选择下标 0 和 1 ,插入 nums[0] % nums[1] 到数组末尾,得到 [5,5,0,0] ,然后删除下标为 0 和 1 的元素。 nums 变为 [0,0] 。 nums 的长度无法进一步减小,所以答案为 2 。 2 是可以得到的最小长度。
示例 3:
输入:nums = [2,3,4] 输出:1 解释:使数组长度最小的一种方法是: 操作 1 :选择下标 1 和 2 ,插入 nums[1] % nums[2] 到数组末尾,得到 [2,3,4,3] ,然后删除下标为 1 和 2 的元素。 nums 变为 [2,3] 。 操作 2 :选择下标 1 和 0 ,插入 nums[1] % nums[0] 到数组末尾,得到 [2,3,1] ,然后删除下标为 1 和 0 的元素。 nums 变为 [1] 。 nums 的长度无法进一步减小,所以答案为 1 。 1 是可以得到的最小长度。
提示:
1 <= nums.length <= 1051 <= nums[i] <= 109
解题思路
方法一:分情况讨论
我们不妨记数组 的最小的元素为 。
如果 只出现一次,那么我们将 与数组 的其他元素进行操作,可以将其他元素全部消去,最终剩下 一个元素,答案为 。
如果 出现多次,我们判断数组 中的元素是否都是 的倍数。如果不是,即存在至少一个元素 ,使得 ,说明我们可以通过操作,构造出一个小于 的元素,那么这个小于 的元素与其他元素进行操作,可以将其他元素全部消去,最终剩下这个小于 的元素,答案为 ;如果都是 的倍数,我们可以先借助 ,将所有大于 的元素消去,最终剩下的元素都是 ,个数为 ,两两配对,每两个元素进行一次操作,最终剩下 个元素,答案为 。
时间复杂度 ,其中 是数组 的长度。空间复杂度 。
class Solution:
def minimumArrayLength(self, nums: List[int]) -> int:
mi = min(nums)
if any(x % mi for x in nums):
return 1
return (nums.count(mi) + 1) // 2
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Look for a solid understanding of greedy strategies and their implementation in reducing array length.
- question_mark
Evaluate how well the candidate handles edge cases, such as arrays with repeated elements or when the modulus operation does not significantly reduce the array.
- question_mark
Assess the candidate's ability to justify the sequence of operations and whether they can explain the rationale behind choosing specific pairs for modulus.
常见陷阱
外企场景- error
Failing to account for the most optimal pairings that reduce the array length effectively.
- error
Overlooking edge cases where the array cannot be minimized further due to redundant modulus operations.
- error
Misunderstanding the operation's effect on the array, especially when it seems like the array length will not decrease significantly.
进阶变体
外企场景- arrow_right_alt
Allow only a limited number of operations and ask for the minimal achievable length after those operations.
- arrow_right_alt
Change the operation to insert nums[i] * nums[j] instead of modulus and test how that affects the minimal length.
- arrow_right_alt
Limit the number of times any element can be involved in an operation and ask for the minimum array length under that constraint.