另一个面试问题让我在最短的计算时间内找到一个排序数组的重复值的最大可能子阵列。
Let input array be A[1 ... n]
Find an array B of consecutive integers in A such that:
for x in range(len(B)-1):
B[x] == B[x+1]
我认为最好的算法是将数组分成两半并从中间向外进行比较,并从中间比较整数,并从中间找到相同整数的最长应变。然后我会通过将数组分成两半并在两半上调用方法来递归地调用该方法。
我的采访者说我的算法很好,但是我的算法是O(logn)的分析是不正确的,但从来没有告诉我正确的答案是什么。我的第一个问题是这个算法的Big-O分析是什么? (请尽可能多地展示工作!Big-O不是我的强项。)我的第二个问题纯粹是出于好奇,是否有更高效的算法?
答案 0 :(得分:4)
此问题的最佳解决方案是O(n)
解决方案,因此您的算法可能无法正确且O(lg n)
。
例如,考虑数组中不包含重复元素的情况。要确定这一点,需要检查每个元素,并检查每个元素是O(n)
。
这是一个简单的算法,可以找到重复元素的最长子序列:
start = end = 0
maxLength = 0
i = 0
while i + maxLength < a.length:
if a[i] == a[i + maxLength]:
while i + maxLength < a.length and a[i] == a[i + maxLength]:
maxLength += 1
start = i
end = i + maxLength
i += maxLength
return a[start:end]
如果你有理由相信子序列会很长,你可以将maxLength
的初始值设置为一些启发式选择的值以加快速度,然后只查找较短的序列如果找不到一个(即你在第一次通过后最终得到end == 0
。)
答案 1 :(得分:0)
我认为我们都同意,在最坏的情况下,A
的所有内容都是唯一的,或者A
的所有内容都相同,您必须检查数组中的每个元素以确定没有重复或确定所有数组包含一个数字。就像其他海报所说的那样,那将是O(N)
。我不确定鸿沟虽然你可以通过使用递归来简化代码,但是征服可以帮助你解决这个算法的复杂性。划分&amp;当你可以丢弃大部分输入时(例如二进制搜索),征服真的有助于减少Big O,但是在你可能需要检查所有输入的情况下,它不会有太大的不同。
我假设结果是你只是返回你找到的最大B的大小,尽管你可以很容易地修改它以返回B。
所以在算法方面,鉴于A是有序的,我不确定答案会比按顺序遍历数组更快/更简单。似乎最简单的答案是有2个指针,一个从索引0开始,一个从索引1开始。比较它们然后将它们两者递增;每次它们相同时,你向上勾选一个计数器给你当前的B
大小,当它们不同时,你将该计数器重置为零。您还可以保留目前为止找到的B的最大大小的变量,并在每次找到更大的B
时更新它。
答案 2 :(得分:0)
在此算法中,访问n
元素时每个访问元素的计算次数不变,因此运行时间为O(n)
。
给定排序数组A[1..n]
:
max_start = max_end = 1
max_length = 1
start = end = 1
while start < n
while A[start] == A[end] && end < n
end++
if end - start > max_length
max_start = start
max_end = end - 1
max_length = end - start
start = end
答案 3 :(得分:-1)
假设最长的连续整数只有长度为1,那么您将扫描n个项目的整个数组A.因此,复杂性不是n,而是len(B)。
不确定复杂性是否为O(n / len(B))。
检查2边缘情况
- 当n == len(B)时,你得到即时结果(只检查A [0]和A [n-1]
- 当n == 1时,你得到O(n),检查所有元素
- 正常情况下,我懒得写算法来分析......
修改强>
鉴于事先不知道len(B)
,我们必须采取最坏的情况,即O(n)