遇到“两笔”编码挑战变体的问题?

时间:2018-01-17 17:53:57

标签: python algorithm

这两个问题试图找到xy两个元素,x+y=target。这可以使用强力方法来实现。

for x in arr:
    for y in arr:
        if x+y==target:
             return [x,y]

我们正在for循环中进行一些冗余计算 - 也就是说我们只想考虑两个元素的组合。我们可以按如下方式进行N C 2双循环。

for i, x in enumerate(arr):
    if y in arr[i+1:]:
        if x+y==target:
             return [x,y]

我们节省了很大的时间复杂因素。现在让我们注意,内部循环是一个搜索。我们可以使用哈希搜索或二进制搜索。

seen = set()
for i, x in enumerate(arr):      
    if target-x in seen:
        y = target-x
        return [x,y]
    seen.add(x)

并非只看到i的长度。它只会在击中第二个数字时触发(因为它的补码必须在集合中)。

此问题的一个变体是:查找满足以下x-y = target的元素。这是一个简单的变体,但它为这个问题增加了一点逻辑复杂性。

我的问题是:为什么以下不起作用?也就是说,我们只是修改了以前的代码?

seen = set()
for i, x in enumerate(arr):      
    for x-target in seen:
        y = x-target
        return [x,y]
    seen.add(x)       

我问过一个朋友,但是我不理解他。他说减法不是联想的。我们在二和问题中利用加法的关联性来实现恒定的时间改进。但这就是他告诉我的全部。老实说我不明白。我仍然认为我的代码应该有效。有人能告诉我为什么我的代码不起作用吗?

1 个答案:

答案 0 :(得分:0)

您的算法(一旦if / for混合被修复)仍然不起作用,因为减法不是可交换的。该算法仅有效地检查xy对,其中x在数组中的位置比y更晚。在测试x+y = target时没关系,因为这两个值的顺序无关紧要。但对于x-y = target,顺序确实很重要,因为x - y不是同一个y - x

对此的修复方法是检查数组中的每个数字,看看它是x还是y,而另一个值是来自arr的早期值之一。每个都需要进行不同的检查,因此在循环中可能需要两个if语句:

seen = set()
for n in arr:      
    if n-target in seen:
        x = n
        y = n-target
        return [x,y]

    if n+target in seen:
        x = n+target
        y = n
        return [x,y]

    seen.add(x)

请注意,我将循环变量重命名为n,因为它可能是xy,具体取决于算法的运算方式。在x语句的主体中使用yif变量并非绝对必要,您可以直接在return语句中进行这些计算。我还删除了不需要的enumerate调用,因为代码的单循环版本根本不使用i