LeetCode 题解工作台
将元素分配到两个数组中 II
给你一个下标从 1 开始、长度为 n 的整数数组 nums 。 现定义函数 greaterCount ,使得 greaterCount(arr, val) 返回数组 arr 中 严格大于 val 的元素数量。 你需要使用 n 次操作,将 nums 的所有元素分配到两个数组 arr1 和 arr2 中…
4
题型
5
代码语言
3
相关题
当前训练重点
困难 · 数组·结合·二分·indexed·树
答案摘要
我们可以用两个树状数组 `tree1` 和 `tree2` 分别维护 `arr1` 和 `arr2` 中小于等于某个数的元素个数。每一次,我们在树状数组中查询小于等于当前数的元素个数,那么大于当前数的元素个数就是当前数组的长度减去查询的结果。然后我们就可以根据这个差值来决定将当前数加入到哪个数组中。 由于题目中给出的数的范围很大,所以我们需要对这些数进行离散化。我们可以将这些数排序后去重,然后用二…
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 数组·结合·二分·indexed·树 题型思路
题目描述
给你一个下标从 1 开始、长度为 n 的整数数组 nums 。
现定义函数 greaterCount ,使得 greaterCount(arr, val) 返回数组 arr 中 严格大于 val 的元素数量。
你需要使用 n 次操作,将 nums 的所有元素分配到两个数组 arr1 和 arr2 中。在第一次操作中,将 nums[1] 追加到 arr1 。在第二次操作中,将 nums[2] 追加到 arr2 。之后,在第 i 次操作中:
- 如果
greaterCount(arr1, nums[i]) > greaterCount(arr2, nums[i]),将nums[i]追加到arr1。 - 如果
greaterCount(arr1, nums[i]) < greaterCount(arr2, nums[i]),将nums[i]追加到arr2。 - 如果
greaterCount(arr1, nums[i]) == greaterCount(arr2, nums[i]),将nums[i]追加到元素数量较少的数组中。 - 如果仍然相等,那么将
nums[i]追加到arr1。
连接数组 arr1 和 arr2 形成数组 result 。例如,如果 arr1 == [1,2,3] 且 arr2 == [4,5,6] ,那么 result = [1,2,3,4,5,6] 。
返回整数数组 result 。
示例 1:
输入:nums = [2,1,3,3] 输出:[2,3,1,3] 解释:在前两次操作后,arr1 = [2] ,arr2 = [1] 。 在第 3 次操作中,两个数组中大于 3 的元素数量都是零,并且长度相等,因此,将 nums[3] 追加到 arr1 。 在第 4 次操作中,两个数组中大于 3 的元素数量都是零,但 arr2 的长度较小,因此,将 nums[4] 追加到 arr2 。 在 4 次操作后,arr1 = [2,3] ,arr2 = [1,3] 。 因此,连接形成的数组 result 是 [2,3,1,3] 。
示例 2:
输入:nums = [5,14,3,1,2] 输出:[5,3,1,2,14] 解释:在前两次操作后,arr1 = [5] ,arr2 = [14] 。 在第 3 次操作中,两个数组中大于 3 的元素数量都是一,并且长度相等,因此,将 nums[3] 追加到 arr1 。 在第 4 次操作中,arr1 中大于 1 的元素数量大于 arr2 中的数量(2 > 1),因此,将 nums[4] 追加到 arr1 。 在第 5 次操作中,arr1 中大于 2 的元素数量大于 arr2 中的数量(2 > 1),因此,将 nums[5] 追加到 arr1 。 在 5 次操作后,arr1 = [5,3,1,2] ,arr2 = [14] 。 因此,连接形成的数组 result 是 [5,3,1,2,14] 。
示例 3:
输入:nums = [3,3,3,3] 输出:[3,3,3,3] 解释:在 4 次操作后,arr1 = [3,3] ,arr2 = [3,3] 。 因此,连接形成的数组 result 是 [3,3,3,3] 。
提示:
3 <= n <= 1051 <= nums[i] <= 109
解题思路
方法一:离散化 + 树状数组
我们可以用两个树状数组 tree1 和 tree2 分别维护 arr1 和 arr2 中小于等于某个数的元素个数。每一次,我们在树状数组中查询小于等于当前数的元素个数,那么大于当前数的元素个数就是当前数组的长度减去查询的结果。然后我们就可以根据这个差值来决定将当前数加入到哪个数组中。
由于题目中给出的数的范围很大,所以我们需要对这些数进行离散化。我们可以将这些数排序后去重,然后用二分查找来找到每个数在排序后的数组中的位置。
时间复杂度 ,空间复杂度 。其中 是数组 nums 的长度。
class BinaryIndexedTree:
__slots__ = "n", "c"
def __init__(self, n: int):
self.n = n
self.c = [0] * (n + 1)
def update(self, x: int, delta: int) -> None:
while x <= self.n:
self.c[x] += delta
x += x & -x
def query(self, x: int) -> int:
s = 0
while x:
s += self.c[x]
x -= x & -x
return s
class Solution:
def resultArray(self, nums: List[int]) -> List[int]:
st = sorted(set(nums))
m = len(st)
tree1 = BinaryIndexedTree(m + 1)
tree2 = BinaryIndexedTree(m + 1)
tree1.update(bisect_left(st, nums[0]) + 1, 1)
tree2.update(bisect_left(st, nums[1]) + 1, 1)
arr1 = [nums[0]]
arr2 = [nums[1]]
for x in nums[2:]:
i = bisect_left(st, x) + 1
a = len(arr1) - tree1.query(i)
b = len(arr2) - tree2.query(i)
if a > b:
arr1.append(x)
tree1.update(i, 1)
elif a < b:
arr2.append(x)
tree2.update(i, 1)
elif len(arr1) <= len(arr2):
arr1.append(x)
tree1.update(i, 1)
else:
arr2.append(x)
tree2.update(i, 1)
return arr1 + arr2
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Look for an understanding of Binary Indexed Tree (BIT) and its application to dynamic counting.
- question_mark
Evaluate the candidate’s ability to simulate the problem conditions with efficient data structures.
- question_mark
Check for a clear explanation of handling the array insertion logic while maintaining efficiency.
常见陷阱
外企场景- error
Failing to efficiently track counts of greater elements using an appropriate data structure.
- error
Incorrectly handling tie-breakers when both arrays have the same count of greater elements.
- error
Not managing the balance between the two arrays properly, leading to incorrect results.
进阶变体
外企场景- arrow_right_alt
Change the distribution rule, for example, append to the array with fewer elements instead of the one with fewer greater elements.
- arrow_right_alt
Instead of using a Binary Indexed Tree, try using a Segment Tree for the counting operation.
- arrow_right_alt
Increase the number of arrays from two to three or more, with different insertion conditions.