【发布时间】:2017-11-20 18:07:45
【问题描述】:
我的问题类似于Find all elements that appear more than n/4 times in linear time,给你一个大小为n的数组,找出所有出现n/4次以上的元素,不同的是数组是排序的,运行时应该比O( n)。
我的做法是对每个元素在位置n/4、n/2和3*n/4的第一次出现做3次二分查找,由于数组是排序的,我们可以知道每个元素出现的次数是否多于n /4 次通过检查下一个 n/4 元素是否具有相同的值。
我用python3写了如下代码,大家觉得我的做法对不对,有什么可以简化的吗?:
import bisect
# return -1 if x doesn't exist in arr
def binary_search(arr, x):
pos = bisect.bisect_left(arr, x)
return pos if pos != len(arr) and arr[pos] == x else -1
def majority(arr):
n = len(arr)
output = []
quarters = [arr[n//4],arr[n//2],arr[3*n//4]]
# avoid repeating answer in output array
if arr[n//4] == arr[n//2]:
quarters.remove(arr[n//4])
quarters.remove(arr[n//2])
output.append(arr[n//2])
if arr[n//2] == arr[3*n//4]:
if arr[n//2] in arr:
quarters.remove(quarters[n//2])
if arr[3*n//4] in arr:
quarters.remove(quarters[3*n//4])
if arr[n//2] not in output:
output.append(arr[n//2])
for quarter in quarters:
pos = binary_search(arr, quarter)
if pos != -1 and pos+n//4 < len(arr) and arr[pos] == arr[pos+n//4]:
output.append(arr[pos])
return output
print(majority([1,1,1,6,6,6,9,145]))
【问题讨论】:
-
我认为避免重复答案会使事情变得更加困难。你是正确的,如果一个元素出现 1/4 或更多的时间,它在
quarter中至少出现一次。但是您的删除方法是错误的。因为如果arr[n//4] == arr[n//2],那么您将两者都删除,但现在有一个更改是您删除了所有出现的事件。 -
NlogN 并不比 O(N) 好
-
@LuaiGhunim:但列表作为先决条件排序。
-
您描述的方法听起来不对。例如,如果一个项目出现 (n/4)+1 次,它可以从例如位置 2 开始并在位置 (n/4)+2 结束。该元素将出现在位置 (n/4),但不会出现在位置 0 或 (n/2)。如果您的代码实现了您所描述的,那就错了。如果您的代码有效,那么它不会实现您所描述的内容。
-
@JimMischel:你有这方面的示例输入吗?如果 array[n/4] == 1,我的算法会找到第一次出现的 1,假设它在 2,然后它会检查 array[2+n/4] == array[2] 以验证它是否出现超过 n/4 次。
标签: python arrays algorithm python-3.x refactoring