【二分法,双指针】3134.找出唯一性数组的中位数
2024-08-27 16:04:28
Problem: 3134. 找出唯一性数组的中位数
难度分2451,这里记录对于官解的理解。
思路
观察提示中数组的长度,可知这题使用$O(n^2)$复杂度的解法都会超时,而所有非空子数组共有n*(n+1)/2
个,显然是不可行的。因此需要考虑二分法。如果二分法可行,再加上数组的单遍遍历,复杂度为$O(nlogn)$,就不会超时。
要使用二分法,首先我们需要保证二分查找的数组是有序的。
这里的有序是广义的有序,只需要保证在某个性质上是有序的即可。
首先,我们观察到t
越大,唯一性数组中t出现的次数不一定越多,这个性质可以排除。
因此另找一个性质。对于以答案为下标的数组,设t
为答案的某个值(即数组下标),对于性质数组nums中不同元素个数不大于t的非空子数组个数ct,该数组是有序的。也就是说,t
的值越大,ct
的值也就越大。
这里数组的元素是累加性质的,所以一定递增,可以作为一种二分的思考选择。
同时我们可以注意到,对于不同元素个数为t
的nums
数组切片nums[j...i]
,其子数组的不同元素个数也不大于t
。如果我们使用下标i
遍历nums
数组,并且每一轮都把j
到i
之间的取值作为左端点,i
作为右端点的所有i-j+1
个数组累加到ct
中,我们最后就可以得到ct
的值。
而j
和i
的值都可以通过滑动窗口来找到,用一个哈希表来存储不同元素的个数,大于t时下把j
右移并更新哈希表,直到哈希表的元素个数不大于t
。
使用滑动窗口才能达成$O(n)$复杂度,对于子数组的问题非常有用。
对于二分答案,上界为n
,下界为1
,我们要寻找的中位数在数组的(n*(n+1)/2+1)/2
的位置上,只要找到不小于该数的最小ct
值,t就是要求的答案。
复杂度
- 时间复杂度: $O(nlogn)$:二分法$logn$,滑动窗口$n$。
- 空间复杂度: $O(n)$:哈希表的开销。
Code
1 | class Solution { |