在差小于或等于K的数组中找到所有数字

时间:2019-02-15 02:41:43

标签: python arrays

我想找到两个数字A[i]A[j],它们的差小于或等于K,因此我需要将这样的数字的索引存储在数组L(左)R(右)并返回L&R

def fun(A, k): 
    n = len(A)
    l = 0
    r = n-1
    # traverse the array for the two elements 
    while l<r: 
        if (A[l] - A[r] <= n):
            return A[l],A[r]
        elif (A[l] - A[r] < n): 
            l += 1
        else: 
            r -= 1
    return 0

# Driver code to test above function 
A = [3.5,5,6,12,13] 
k = 1.7
print(fun(A, k))

预期输出:

L[0,0,1,3,3],R[1,2,2,4,4]

2 个答案:

答案 0 :(得分:2)

您应该使用itertools.combinations获取所有可能的组合,然后测试它们之间的差异并在需要时附加。

from itertools import combinations

def fun(A, k):
    l, r = [], []
    for (x_idx, x_val), (y_idx, y_val) in combinations(enumerate(A), 2):
        if abs(x_val - y_val) <= k:
            l.append(x_idx)
            r.append(y_idx)
    return l, r

测试:

A = [3.5,5,6,12,13] 
k = 1.7
print(fun(A, k))
# ([0, 1, 3], [1, 2, 4])

尽管这不是您的预期输出,但根据您的逻辑,我觉得您的预期输出可能会有一些错误。

答案 1 :(得分:0)

一个利用示例O(n log n)中的排序方式的A解决方案(如果未排序,您总是可以第二次支付O(n log n)对其进行排序,尽管保留原始索引会可能不值得付出复杂性):

from bisect import bisect

def fun(A, k):
    # Add A.sort() if A not guaranteed to be sorted
    for l, x in enumerate(A):
        for r in range(l+1, bisect(A, x+k, l+1)):
            yield l, r

这使用the bisect.bisect function查找O(log n)时间中每个起点的终点,从而使总成本为O(n log n)。它甚至不需要直接针对k测试大多数值,因为bisect会找到满足不同条件的索引的末尾,并且介于两者之间的所有值一定都满足它。

我不是手动构建list,而是使它成为一个生成器函数,可以使用L并将其解压缩为Rzip值:< / p>

>>> A = [3.5,5,6,12,13] 
>>> k = 1.7
>>> L, R = zip(*fun(A, k))
>>> print(L, R)
(0, 1, 3), (1, 2, 4)

您可以显式使用list来做到这一点:

def fun(A, k):
    L, R = [], []
    for l, x in enumerate(A):
        newr = range(l+1, bisect(A, x+k, l+1))
        L += [l] * len(newr)
        R.extend(newr)
    return L, R

但我有点像generator-> zip-> unpack方法,用于让Python完成大部分工作。无论哪种方式,O(n log n)的理论成本都比O(n * (n - 1) / 2)(大致为O(n ** 2))好。