【每日一题】Leetcode 1287. 有序数组中出现次数超过25%的元素
简单
数组
二分查找
给你一个非递减的 有序 整数数组,已知这个数组中恰好有一个整数,它的出现次数超过数组元素总数的 25%。
请你找到并返回这个整数
示例:
输入:arr = [1,2,2,6,6,6,6,7,10] 输出:6
提示:
1 <= arr.length <= 10^4 0 <= arr[i] <= 10^5
思路 1:(遍历,时间复杂度\(O(n)\))
- 从左至右遍历数组,记录元素出现次数,当次数大于长度的 25% 后直接返回当前元素
- 由于是有序列表,所以当当前元素变化时,直接更新元素出现次数和当前元素。
代码 1:(遍历,时间复杂度\(O(n)\))
class Solution:
def findSpecialInteger(self, arr: List[int]) -> int:
threshold = len(arr)
cur = None
cur_count = 0
for item in arr:
if item != cur:
if cur_count * 4 > threshold: # 不使用 threshold * 0.25 是为了保证不被浮点精度影响
return cur
cur_count = 0
cur = item
cur_count += 1
return cur
思路 2:(二分查找,时间复杂度\(O(log(n))\))
- 数学归纳法:设满足要求的答案为 x,数组为 arr
① 当 x 至少出现 span = 1 次时,其必定在 [arr[0], arr[1], arr[2], ... arr[span i], arr[span (i + 1)]]中
② 当 x 至少出现 2 次时,其必定在 [arr[0], arr[2], arr[4], ..., arr[span i], arr[span (i + 1)]]
...
③ 当 x 至少出现 span = len(arr) // 4 + 1 次时,其必定在 [arr[0], arr[span], arr[span 2], ..., arr[span i], arr[span * (i + 1)] - 所以根据 1 中得到的数组进行查找,并判断查找到的元素的位置区间。
- python 中可以使用 bisect 模块中的 bisect.bisect_left 和 bisect.bisect_right 分别查找元素的左侧位置和右侧位置
知识点:bisect 可用于
代码 2:(二分查找,时间复杂度\(O(log(n))\))
class Solution:
def findSpecialInteger(self, arr: List[int]) -> int:
n = len(arr)
span = n // 4 + 1
for i in range(0, n, span):
iter_l = bisect.bisect_left(arr, arr[i])
iter_r = bisect.bisect_right(arr, arr[i])
if iter_r - iter_l >= span:
return arr[i]
return -1
感谢浏览,欢迎关注祁彧w博客!
文章评论