确定数组是否包含两个等于某个总和的元素?

J.L*_*J.L 4 java algorithm performance

// Checks whether the array contains two elements whose sum is s.
// Input: A list of numbers and an integer s
// Output: return True if the answer is yes, else return False

public static boolean calvalue (int[] numbers, int s){
for (int i=0; i< numbers.length; i++){
    for (int j=i+1; j<numbers.length;j++){
        if (numbers[i] < s){
            if (numbers[i]+numbers[j] == s){
                return true;
                }
            }
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

che*_*ken 12

这可以在O(n)中实现.

  1. 从列表中创建一个哈希支持的集合,使其包含列表的所有元素.这需要O(n).
  2. 遍历n列表中的每个元素,计算s-n = d并检查d集合中是否存在.如果d存在,那么n+d = s,返回true.如果您在没有找到合适的情况下通过列表d,则返回false.这是通过列表的单次传递实现的,每次查找都采用O(1),因此该步骤也需要O(n).

  • 最初,该集合将包含5和2.当您开始遍历arra时,它找到的第一个元素是"5".然后你在5和...的集合中查找它.你去.在那.因此它认为它发现了5并且错误地返回true.我想稍微修改就可以解决这个问题.使用地图而不是集合.然后保持每个数字的计数.如果您发现它的数量超过1,那么您就得到了答案. (2认同)

nha*_*tdh 5

你可以通过对数组进行排序来解决这个问题,然后保持2个指向数组开始和结束的指针,并通过移动两个指针找到2个数字.排序步骤采用O(nlog n),第二步采用O(n).

正如@Adam指出的那样,从数组中删除重复元素也是很好的,这样如果数组包含许多重复数字,您可以减少第二步的时间.

至于如何做第二步:

  • 如果当前2个数字的总和大于n,则向后移动指针.
  • 如果当前2个数字的总和小于n,则将指针向前移动.
  • 当两个指针指向同一个元素时停止并拒绝.如果sum等于n,则接受.

为什么这是正确的(我使用右端表示较大的末端,左端表示较小的末端):

  • 如果sum大于n,则使用右端没有意义,因为大于当前左端的所有数字都会使其变差.
  • 如果sum小于n,则使用左端没有意义,因为所有小于当前右端的数字都会使其变差.
  • 在每一步中,我们将在删除的数字和剩余的数字之间经历所有可能的组合(逻辑上).最后,我们将耗尽所有数字对之间可能的所有组合.


归档时间:

查看次数:

20379 次

最近记录:

10 年,4 月 前