Algorithm 具有相同和的两对数

Algorithm 具有相同和的两对数,algorithm,list,integer,Algorithm,List,Integer,给定一个(不一定是不同的)整数的列表,确定是否存在成对的不同索引w,x,y,z,从而a_w+a_x=a_y+a_z 我知道一种方法是对循环使用4个级别的,每个级别迭代一个索引。当我们得到相等的和时,检查所有的指数是否两两不同。如果是,则返回true。如果我们已经用尽了所有的可能性,返回false。这有运行时间O(n^4) 我们能做得更好吗?计算a_w+a_x的所有可能值,将它们插入哈希表。将(a_w+a_x,w)和(a_w+a_x,x)插入第二个哈希表 在向第一个哈希表插入值之前,请检查该值是否

给定一个(不一定是不同的)整数的列表,确定是否存在成对的不同索引
w,x,y,z
,从而
a_w+a_x=a_y+a_z

我知道一种方法是对循环使用4个级别的
,每个级别迭代一个索引。当我们得到相等的和时,检查所有的指数是否两两不同。如果是,则返回
true
。如果我们已经用尽了所有的可能性,返回
false
。这有运行时间
O(n^4)


我们能做得更好吗?

计算
a_w+a_x
的所有可能值,将它们插入哈希表。将(a_w+a_x,w)和(a_w+a_x,x)插入第二个哈希表

在向第一个哈希表插入值之前,请检查该值是否已在表中。如果是,请检查第二个表。如果存在(a_w+a_x,w)或(a_w+a_x,x)中的任何一个,不要插入任何内容(我们有一个重复的元素)。如果这两对都不在第二张表中,我们得到了肯定的答案

如果在处理完所有(w,x)对之后,我们没有得到肯定的答案,这意味着不存在这样的成对不同索引

时间复杂度为O(n2)。空间要求也是O(n2)

在O(n)空间中也可以这样做,但是O(n2*log(n))时间,根据这个答案稍微修改一下算法:

  • 对列表进行排序
  • 对元素使用优先级队列,包含
    a_w+a_x
    作为键和
    w,x
    作为值。用
    n-1
    元素预填充此队列,其中x=0,w=1。。n-1
  • 重复从该队列中弹出最小元素
    (总和,w,x)
    ,并将元素
    (a_w+a_x_+u 1,w,x+1)
    放入队列(但当x>=w时不要放入元素)。当从队列中删除的两个连续元素的和相同时停止
  • 要处理重复项,可以比较两个具有相等和的连续元素的w,x。但使用krjampani的预处理思想更容易。如果排序列表包含两对重复项,或者单个元素重复了4次,则成功。否则,复制的值不超过一个;在列表中只保留它的一个实例,并将它的加倍值与一对“特殊”索引一起添加到优先级队列中:(2a,-1,-1)

  • 通过对原始数组进行如下预处理,可以简化Evgeny的解决方案

    我们首先使用哈希表来计算原始数组中每个元素的频率。如果至少有2个元素具有重复项(其频率至少为2),或者如果元素出现的频率至少为4,则答案为
    true
    。否则,如果元素
    a
    以2或3的频率出现,我们将
    2a
    添加到第二个哈希表中,并将
    a
    的所有副本替换为原始数组中的单个副本


    然后在修改后的数组中,对于每对索引
    i
    j
    i
    ,我们将
    a_i+a_j
    添加到第二个哈希表中,如果我们在该哈希表中发现重复项,则返回
    true

    如果您有8.5GB内存(无符号整数更多,如果总和或索引未跨越整个整数范围则更少),创建三个数组。首先,对每个可能的和使用1位。这是一个结果位图。第二,对每个可能的和使用32位。它记录索引j。第三,对每个可能的和使用1位。这是一个位字段,记录当前迭代中是否遇到了该和——每次迭代都将其归零。迭代i=0…n和j=i+1…n。对于each sum,查看是否在第一个位字段中设置(如果以前遇到过)。如果是,则查看第二个数组中记录的索引是否与i或j匹配(如果旧j与新i或新j匹配)。如果不是,则检查第二个数组中的位是否已设置(如果它是在当前迭代中设置的,因此旧i与新i匹配)。如果不匹配,则有一个匹配项!(旧i将永远不会匹配旧j或新j,新i将永远不会匹配新j。)退出。否则,在所有三个数组中记录总和并继续


    虽然它使用了价值40美元的内存(我喜欢现在的:),但这可能比使用散列映射和装箱快得多。对于大n,甚至可能使用更少的内存。一个缺点是数据几乎永远不会在二级缓存中。但是试着将JVM设置为使用大页面,这样至少TLB丢失不会进入主内存。这是o(n^2)用于处理,o(1)用于内存。

    您想要一个布尔答案,如“是”中的“有匹配项”,还是想要一个匹配项列表?布尔答案…“确定是否存在两两不同的索引”但是你怎么知道索引是不是两两不同呢?@John:通过在循环中的构造。不要在
    i in 1..n,j in 1..n
    上循环,而是在
    i in 1..n-1,j in i..n
    上循环。是的,但我们希望
    w,x,y,z
    两两不同。@John:将索引插入哈希映射(总和是键,索引列表是值),在第二步筛选出所有匹配的索引。@冒名顶替者:如果O(n^2)空间不可接受,则有其他算法,在答案中引用。