Algorithm 将一个数组拆分为2个子数组并递归求解它们仍然是O(log(n))?
我发现了这个算法,它可以计算上两个排序列表的中位数。 它说,它是O(log(n))。 但真的是这样吗 我感到困惑的是: 这些行将数组拆分为2个子数组(使用Python的切片)并递归求解:Algorithm 将一个数组拆分为2个子数组并递归求解它们仍然是O(log(n))?,algorithm,runtime,time-complexity,Algorithm,Runtime,Time Complexity,我发现了这个算法,它可以计算上两个排序列表的中位数。 它说,它是O(log(n))。 但真的是这样吗 我感到困惑的是: 这些行将数组拆分为2个子数组(使用Python的切片)并递归求解: if n % 2 == 0: return getMedian(arr1[:int(n / 2) + 1], arr2[int(n / 2) - 1:], int(n / 2) + 1) else: return getMedian(arr1[:int(n / 2) + 1],
if n % 2 == 0:
return getMedian(arr1[:int(n / 2) + 1],
arr2[int(n / 2) - 1:], int(n / 2) + 1)
else:
return getMedian(arr1[:int(n / 2) + 1],
arr2[int(n / 2):], int(n / 2) + 1)
但是对我来说,分割数组看起来像O(n)。
所以在我看来,整个算法必须是O(n*logn)
在这里,您可以看到我所说的算法的全部代码:
# using divide and conquer we divide
# the 2 arrays accordingly recursively
# till we get two elements in each
# array, hence then we calculate median
#condition len(arr1)=len(arr2)=n
def getMedian(arr1, arr2, n):
# there is no element in any array
if n == 0:
return -1
# 1 element in each => median of
# sorted arr made of two arrays will
elif n == 1:
# be sum of both elements by 2
return (arr1[0]+arr2[1])/2
# Eg. [1,4] , [6,10] => [1, 4, 6, 10]
# median = (6+4)/2
elif n == 2:
# which implies median = (max(arr1[0],
# arr2[0])+min(arr1[1],arr2[1]))/2
return (max(arr1[0], arr2[0]) +
min(arr1[1], arr2[1])) / 2
else:
#calculating medians
m1 = median(arr1, n)
m2 = median(arr2, n)
# then the elements at median
# position must be between the
# greater median and the first
# element of respective array and
# between the other median and
# the last element in its respective array.
if m1 > m2:
if n % 2 == 0:
return getMedian(arr1[:int(n / 2) + 1],
arr2[int(n / 2) - 1:], int(n / 2) + 1)
else:
return getMedian(arr1[:int(n / 2) + 1],
arr2[int(n / 2):], int(n / 2) + 1)
else:
if n % 2 == 0:
return getMedian(arr1[int(n / 2 - 1):],
arr2[:int(n / 2 + 1)], int(n / 2) + 1)
else:
return getMedian(arr1[int(n / 2):],
arr2[0:int(n / 2) + 1], int(n / 2) + 1)
# function to find median of array
def median(arr, n):
if n % 2 == 0:
return (arr[int(n / 2)] +
arr[int(n / 2) - 1]) / 2
else:
return arr[int(n/2)]
# Driver code
arr1 = [1, 2, 3, 6]
arr2 = [4, 6, 8, 10]
n = len(arr1)
print(int(getMedian(arr1,arr2,n)))
# This code is contributed by
# baby_gog9800
是的,绝对是。许多候选人因为错过了这一点而在编程面试中得到了不好的分数 在python中对列表进行切片将生成一个副本 复制列表的一半需要O(n)个时间 这个算法总共需要O(n)个时间(你应该试着找出为什么它不是O(n logn))
您确实需要知道您的语言是如何工作的,才能为任何特定的示例解决这个问题,因为有些语言提供了在不复制元素的情况下对列表进行切片的方法。在java中,您可以调用
list.sublist(start,end)
,例如,在不复制的情况下获取切片。是的,绝对可以。许多候选人因为错过了这一点而在编程面试中得到了不好的分数
在python中对列表进行切片将生成一个副本
复制列表的一半需要O(n)个时间
这个算法总共需要O(n)个时间(你应该试着找出为什么它不是O(n logn))
您确实需要知道您的语言是如何工作的,才能为任何特定的示例解决这个问题,因为有些语言提供了在不复制元素的情况下对列表进行切片的方法。在java中,您可以调用
list.sublist(start,end)
,例如,在不复制的情况下获取切片。这里的问题是您混淆了算法的实现。这个Python实现是O(n)
,因为它执行的是线性时间切片操作,但算法本身是O(log(n))
,因为它实际上不需要执行复制切片中元素的线性时间操作——它可以在相同的列表上操作,而无需创建新的列表。这使得主定理中的f(n)=O(1)
,使得算法的整体运行时间O(logn)
。您可以选择以Python实现该算法,该方法不需要切片(例如,类似于GeeksForGeeks上的C++和java实现),它将运行在算法及其实现之间的区别在于为什么算法分析是在伪代码上执行的,而不是在实际编程语言中执行的。像这样的实现细节常常会引起混乱。因此,算法倾向于根据需求明确说明所使用的操作及其时间复杂性(如索引、切片等) 这里的问题是您混淆了算法的实现。这个Python实现是
O(n)
,因为它执行的是线性时间切片操作,但算法本身是O(log(n))
,因为它实际上不需要执行复制切片中元素的线性时间操作——它可以在相同的列表上操作,而无需创建新的列表。这使得主定理中的f(n)=O(1)
,使得算法的整体运行时间O(logn)
。您可以选择以Python实现该算法,该方法不需要切片(例如,类似于GeeksForGeeks上的C++和java实现),它将运行在算法及其实现之间的区别在于为什么算法分析是在伪代码上执行的,而不是在实际编程语言中执行的。像这样的实现细节常常会引起混乱。因此,算法倾向于根据需求明确说明所使用的操作及其时间复杂性(如索引、切片等) 在Python中,如果对列表进行切片,则创建一个副本,因此需要O(n)。GFG文章中的切片并不创建副本,它只是保存了如何切片列表的指针。它将两个数组拆分为半,因此从2n大小变为n/2+n/2=n,从而将问题减半。虽然如果它只是一个大小为n的数组,那么执行n/2+n/2=n仍然是O(n)。GFG文章中的切片并不创建副本,它只是保存了如何切片列表的指针。它将两个数组拆分为半,因此从2n大小变为n/2+n/2=n,从而将问题减半。虽然如果只是一个大小为n的数组,那么n/2+n/2=n仍然是O(n)。接口方法
List.sublist()
的约定是,它返回原始列表的视图,在没有通过视图以外的结构更改的情况下有效。这使得O(1)实现变得可行和可能,就像在java.util.ArrayList中一样——但不保证。在每次调用getMedian时,我们只调用getMedian一次(如果n>=2)。所以我可以通过主定理证明f(n)=f(n/2)+Θ(n)。(1/2)^1 < 1. 正因为如此,我们把Θ(n)放在了一起?在Java的例子中,它是库,而不是语言。接口方法List.sublist()
的约定是,它返回原始列表的视图,在没有通过视图以外的结构更改的情况下有效。这使得O(1)实现变得可行和可能,就像在java.util.ArrayList中一样——但不保证。在每次调用getMedian时,我们只调用getMedian一次(如果n>=2)。所以我可以通过主定理证明f(n)=f(n/2)+Θ(n)。(1/2)^1 < 1. 正因为如此,我们把Θ(n)都放在一起了?所以我没有切片,而是一直忽略整个数组和另外两个参数l