Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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
Python 从两个排序数组中取前10个元素的最小和组合_Python_Algorithm_Sorting_Iteration_Cartesian Product - Fatal编程技术网

Python 从两个排序数组中取前10个元素的最小和组合

Python 从两个排序数组中取前10个元素的最小和组合,python,algorithm,sorting,iteration,cartesian-product,Python,Algorithm,Sorting,Iteration,Cartesian Product,谷歌没有设法说出这个问题的名称,希望这个问题能对社区有所贡献 假设我们有两个排序的数字数组,如: 2 8 12 18 45 35 85 48 87 49 97 59 我们希望有效地从两个数组中提取前k 10个最小的数和组合。在我们的情况下,这将是: 2 + 8 = 10 2 + 18 = 20 12 + 8 = 20 12 + 18 = 30 2 + 35 = 37 12 + 35 = 47 2 + 48 = 50 2 + 49 = 51 45 + 8 = 53 12 +

谷歌没有设法说出这个问题的名称,希望这个问题能对社区有所贡献

假设我们有两个排序的数字数组,如:

 2  8
12 18
45 35
85 48
87 49
97 59
我们希望有效地从两个数组中提取前k 10个最小的数和组合。在我们的情况下,这将是:

 2 +  8 = 10 
 2 + 18 = 20
12 +  8 = 20
12 + 18 = 30
 2 + 35 = 37
12 + 35 = 47
 2 + 48 = 50
 2 + 49 = 51
45 +  8 = 53
12 + 48 = 60
正确的方法是什么?我设计了一个由@sanyash改进的简单实现,但它没有利用数组被排序的事实,而且问题在线性时间内是可行的

def最小_产品K,arr1,arr2: product_iter=itertools.product itertools.islicearr1,k, itertools.islicearr2,k, 产品分类=分类产品分类,关键字=总和 product_sliced=itertools.isliceproduct_sorted,k; 返回列表产品\u切片 打印产品10, [ 2, 12, 45, 85, 87, 98], [ 8, 18, 35, 48, 49, 59] 类似的问题:但它处理的是创建一个完整的结果数组,而在我的例子中,我只需要前几个值


另外,我添加了python标记,因为这是一个数学问题,但我很乐意使用任何语言的解决方案,或者只是一个解释,或者一个到wikipedia的链接…

首先将两个数组截断为lenk。然后使用以前的实现。没关系^2困难:

import itertools

def smallest_product(k, arr1, arr2):
    product_iter = itertools.product(
        itertools.islice(arr1, k),
        itertools.islice(arr2, k),
    )
    product_sorted = sorted(product_iter, key=sum)[:k]
    return list(product_sorted)


print(smallest_product(
    10, 
    [ 2, 12, 45, 85, 87, 98], 
    [ 8, 18, 35, 48, 49, 59])
)

首先将两个数组截断为lenk。然后使用以前的实现。没关系^2困难:

import itertools

def smallest_product(k, arr1, arr2):
    product_iter = itertools.product(
        itertools.islice(arr1, k),
        itertools.islice(arr2, k),
    )
    product_sorted = sorted(product_iter, key=sum)[:k]
    return list(product_sorted)


print(smallest_product(
    10, 
    [ 2, 12, 45, 85, 87, 98], 
    [ 8, 18, 35, 48, 49, 59])
)

假设我们使用两个数组创建一个表:

for arr in [[i + j for j in arr2] for i in arr1]: print(arr)
我们得到如下输出:

[10, 20, 37, 50, 51, 61]
[20, 30, 47, 60, 61, 71]
[53, 63, 80, 93, 94, 104]
[93, 103, 120, 133, 134, 144]
[95, 105, 122, 135, 136, 146]
[106, 116, 133, 146, 147, 157]
注意,在该矩阵中,矩阵[i][j]==arr1[i]+arr2[j]。所以我们可以计算O1中矩阵任意位置的元素的值。请注意,这是一个排序矩阵,其中所有行和列都是单调递增的,我们试图找到其中的k个最小元素

在这个阶段,OKlogN堆方法变得相当简单。取第一行并将其转换为最小堆。每次弹出最小的元素并将其添加到结果中。每次弹出时,都会将下一行对应列中的元素添加到堆中。重复k次,得到最小的k和


这与实际情况并不完全相关,但是确实存在鞍形搜索的变体,可以让您在ON中而不是像上面的方法那样在OKlogN中找到排序矩阵中的第k个最小元素。可能有一种方法可以将所采用的方法修改为OK,但在这种情况下很可能是矫枉过正

假设我们使用两个数组创建一个表:

for arr in [[i + j for j in arr2] for i in arr1]: print(arr)
我们得到如下输出:

[10, 20, 37, 50, 51, 61]
[20, 30, 47, 60, 61, 71]
[53, 63, 80, 93, 94, 104]
[93, 103, 120, 133, 134, 144]
[95, 105, 122, 135, 136, 146]
[106, 116, 133, 146, 147, 157]
注意,在该矩阵中,矩阵[i][j]==arr1[i]+arr2[j]。所以我们可以计算O1中矩阵任意位置的元素的值。请注意,这是一个排序矩阵,其中所有行和列都是单调递增的,我们试图找到其中的k个最小元素

在这个阶段,OKlogN堆方法变得相当简单。取第一行并将其转换为最小堆。每次弹出最小的元素并将其添加到结果中。每次弹出时,都会将下一行对应列中的元素添加到堆中。重复k次,得到最小的k和

这与实际情况并不完全相关,但是确实存在鞍形搜索的变体,可以让您在ON中而不是像上面的方法那样在OKlogN中找到排序矩阵中的第k个最小元素。可能有一种方法可以将所采用的方法修改为OK,但在这种情况下很可能是矫枉过正

您可以使用堆:

import heapq


def smallest_product(k, a, b):
    k = min(k, len(a) * len(b))
    l = [(a[0] + b[0], 0, 0)]
    heapq.heapify(l)

    seen = set()
    for _ in range(k):
        s, i, j = heapq.heappop(l)

        if i + 1 < len(a) and (i + 1, j) not in seen:
            heapq.heappush(l, (a[i + 1] + b[j], i + 1, j))
            seen.add((i + 1, j))
        if j + 1 < len(b) and (i, j + 1) not in seen:
            heapq.heappush(l, (a[i] + b[j + 1], i, j + 1))
            seen.add((i, j + 1))
        yield (a[i], b[j])

result = list(smallest_product(10, [ 2, 12, 45, 85, 87, 98], [ 8, 18, 35, 48, 49, 59]))

print(result)
上面的代码是中代码的Python翻译。该方法的时间复杂度为Ok*logk

k=11时的输出

您可以使用堆:

import heapq


def smallest_product(k, a, b):
    k = min(k, len(a) * len(b))
    l = [(a[0] + b[0], 0, 0)]
    heapq.heapify(l)

    seen = set()
    for _ in range(k):
        s, i, j = heapq.heappop(l)

        if i + 1 < len(a) and (i + 1, j) not in seen:
            heapq.heappush(l, (a[i + 1] + b[j], i + 1, j))
            seen.add((i + 1, j))
        if j + 1 < len(b) and (i, j + 1) not in seen:
            heapq.heappush(l, (a[i] + b[j + 1], i, j + 1))
            seen.add((i, j + 1))
        yield (a[i], b[j])

result = list(smallest_product(10, [ 2, 12, 45, 85, 87, 98], [ 8, 18, 35, 48, 49, 59]))

print(result)
上面的代码是中代码的Python翻译。该方法的时间复杂度为Ok*logk

k=11时的输出


这个问题可以分三步解决

构造一个长度为m的已排序对的iterables列表,其中m=minlenlist1,k; 对iterables应用see了解更多信息,以获得单个iterable的已排序对,使用每对的总和作为键; 从iterable中获取前k个元素。 m路合并有不同的算法。下面是一个基于堆的实现。复杂性是Ok*logm

from itertools import islice
from heapq import merge

def smallest_pairs(k, list1, list2):
    pairs = map(lambda x:((x, y) for y in list2), islice(list1, k))
    return list(islice(merge(*pairs, key=sum), k))

print(smallest_pairs(10, 
      [ 2, 12, 45, 85, 87, 98],
      [ 8, 18, 35, 48, 49, 59]))

这个问题可以分三步解决

构造一个长度为m的已排序对的iterables列表,其中m=minlenlist1,k; 对iterables应用see了解更多信息,以获得单个iterable的已排序对,使用每对的总和作为键; 从iterable中获取前k个元素。 m路合并有不同的算法。下面是一个基于堆的实现。复杂性是Ok*logm

from itertools import islice
from heapq import merge

def smallest_pairs(k, list1, list2):
    pairs = map(lambda x:((x, y) for y in list2), islice(list1, k))
    return list(islice(merge(*pairs, key=sum), k))

print(smallest_pairs(10, 
      [ 2, 12, 45, 85, 87, 98],
      [ 8, 18, 35, 48, 49, 59]))

谢谢,这肯定是一次升级,不过我想知道是否有比Ok ^2更好的方法。。。我会更新我的问题。谢谢,这肯定会是一个升级,不过我想知道是否
下面是一种比Ok ^2更好的方法。。。我将更新我的问题。可能重复的可能重复的感谢您的解决方案!我无法从一瞥中了解原因,但出于某种原因,对于大于10的k值(如11),它会失败。索引器:列表索引超出范围heapq.heappush,a[i]+b[j+1],i,j+1@ArturKlesun现在看。谢谢你的解决方案!我无法从一瞥中了解原因,但出于某种原因,对于大于10的k值(如11),它会失败。索引器:列表索引超出范围heapq.heappush,a[i]+b[j+1],i,j+1@ArturKlesun现在看。