100246.将元素分配到两个数组中 II
题目描述:
给你一个下标从 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 。
数据范围:
$3\le n \le 10^5, 1\le nums[i] \le 10^9$
题解:
关键在于如何求一个数组中大于 $val$ 的元素个数。如果是有序的,可以直接使用 upper_bound 解决。注意到 multiset是有序的,可以用这个,但是这个返回的是迭代器,求 $it, multiset.end$ 之间的元素个数,只能用 distance,这个复杂度是 $O(n)$ 的,太慢了。
考虑python中的 SortedList,需要导入包from sortedcontainers import SortedList,底层是对 list 的一些优化,返回的还是数组的下标。SortedList.bisect_right()
python中的二分查找,需要导入包 import bisect。bisect_right 查找 >,bisect_left查找 >=。
也有线段树的做法:
可以先对所有的数据排序,离散化,然后把离散化之后的数据作为数组下标,数组中记录出现的次数,这样的话,查询大于 val 的元素个数,只需要求 [val+1,n] 的后缀和。
考虑线段树单点修改,每次对 hash(nums[i]) 下标加 1。然后区间查询,查询区间的元素个数之和。
可以查询 [1, hash(nums[i])] 或者 [hash(nums[i]), n]。
也可以使用树状数组的做法:
代码:
1 | import bisect |
1 | auto optimize_cpp_stdio = []() |
1 | auto optimize_cpp_stdio = []() |