Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 将一个数组拆分为2个子数组并递归求解它们仍然是O(log(n))?_Algorithm_Runtime_Time Complexity - Fatal编程技术网

Algorithm 将一个数组拆分为2个子数组并递归求解它们仍然是O(log(n))?

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],

我发现了这个算法,它可以计算上两个排序列表的中位数。 它说,它是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],  
      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实现),它将运行在O(log n)时间> /P>
算法及其实现之间的区别在于为什么算法分析是在伪代码上执行的,而不是在实际编程语言中执行的。像这样的实现细节常常会引起混乱。因此,算法倾向于根据需求明确说明所使用的操作及其时间复杂性(如索引、切片等)

这里的问题是您混淆了算法的实现。这个Python实现是
O(n)
,因为它执行的是线性时间切片操作,但算法本身是
O(log(n))
,因为它实际上不需要执行复制切片中元素的线性时间操作——它可以在相同的列表上操作,而无需创建新的列表。这使得主定理中的
f(n)=O(1)
,使得算法的整体运行时间
O(logn)
。您可以选择以Python实现该算法,该方法不需要切片(例如,类似于GeeksForGeeks上的C++和java实现),它将运行在O(log n)时间> /P>
算法及其实现之间的区别在于为什么算法分析是在伪代码上执行的,而不是在实际编程语言中执行的。像这样的实现细节常常会引起混乱。因此,算法倾向于根据需求明确说明所使用的操作及其时间复杂性(如索引、切片等)

在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