这是否在O(N log(N))时间内解决3SUM?

时间:2017-09-01 22:25:46

标签: algorithm time-complexity complexity-theory theory

此算法是否作为O(N log(N))中3SUM的解决方案,其中问题由维基百科定义为

  

在计算复杂性理论中,3SUM问题询问一组给定的 n 实数是否包含三个总和为零的元素。

//Given an array of integers called list
//return true if 3 integers in list sum to 0, false otherwise

//quicksort the provided list
quickSort(list)

//add all elements of the list to a hashmap where the key is a number and the value is the number of times it occurs
hs = new hashMap<Integer, Integer>()
for(Integer i:list)
   if(hs.get(i)==null)
        hs.add(i, 1)
    else
        hs.add(i, hs.get(i)+1)

//create a pair of pointers pointing to the left of right of the center of array
startIndex=0
while (list[startIndex]<0 and startIndex<list.length-1)
startIndex++

left=startIndex
right=startIndex+1

//run this loop while pointers are in boundaries of array
while(! (left<0 or right>=list.length)
{
    //see if a 3rd number that can be added to the numbers at left
    //and right to make 0 can be found
    sum=list[left] + list[right]
    negsum= -(sum)
    //if it's found enter these if statements
    if(hs.get(negsum)!=null)
    {
        //check for the possibility that the 3rd number is one of the 1st 2, if not return true 
       if(negsum==list[left] or negsum== list[right])
       {
        //if the 3rd number is one of the 1st 2 make sure that a duplicate of it exists, or if all 3 are 0, that 3 zeros exist
        //if we have enough duplicates, return true
            if(list[left]==list[right] )
                if(list.hasMoreThanTwo(negsum))
                    return true
            else if(list.hasMoreThanOne(negsum))
                return true
       }
       else
           return true
    }

    //if a trio cannot be formed with the numbers at left and right, adjust the pointers so that we will get closer to 0 and try again.
    if (sum<0)
        right++
    else
        left--
}

//if pointers go out of bounds 3 numbers that sum to 0 don't exist
return false

3 个答案:

答案 0 :(得分:1)

您的代码无法处理此案例:

[ - 10,-7,0,0,4,6]。

在这种情况下,右指针会越界,因为左指针位于-10,这太大了。

因此,如果某些事情确实是负面的,那么您的算法将尝试寻找一个积极的解决方案,并最终失败。

答案 1 :(得分:0)

如果我理解这个算法 - 你没有在高级别解释 - 它将不起作用。似乎该方法是从最小幅度的正(右)和负(左)数字开始工作。对于每一对,您要查找第三个数字,然后将一个边界移动到下一个更大的数字,保持2数字和接近0。

问题在于你根本不能保证包含一个相对接近0的数字的三元组。例如,像

[ - 5100,-1700,-1600,-1000 ,,,2500,2600,5000]

正确到2600找到解决方案之前,您会跳过过去-1600到-1700。

答案 2 :(得分:0)

如前所述,您的代码不涉及所有可能的组合。在这里,我将介绍一个测试用例,其中您的代码无法考虑所有可能性。

我们有以下数组:

[101, 100, 100, 0, -50, -199, -200]

为了便于使用,它已经被分类。这转换为:

{101: (1, 0), 100:(2, 1), 0:(1, 2), -50:(1, 3), -199:(1, 4), -200:(1, 5)}
[101, 100, 0, -50, -199, -200]

我们从值的中心开始,在这种情况下为0和-50。

在第一次迭代中,我们可以看到没有任何匹配,因此我们向左移动,因为这将导致更接近的近似。 (0 + -199对100 + -50)

下一次迭代,我们向右移动。 (100 + -199 vs 101 + -50)

之后的迭代,我们再次向右移动,因为它接近于0.(101 + -199 vs 100 + -200)

正如您可能已经注意到的那样,我们刚刚跳过100和-200的配对,这是三联体中的相关对(100,100,-200)。