检查一个数字是否可以从两个整数列表中求和的最快方法?

时间:2014-02-15 02:49:28

标签: java loops math

所以,我有一个整数列表。我需要找出是否可以通过列表中的任何两个数字添加特定数字(非唯一数字)。 到目前为止我所拥有的:

boolean cs = false;
    t:
    for(Integer i1 : primes) {
        for(Integer i2 : primes) {
            if(i1 + i2 == i) {
                cs = true;
                break t;
            }
        }
    }

不幸的是,随着这个列表越来越高(因为每次没有两个总和,它必须找到并创建一个新的和来保持序列运行),这个函数需要指数地执行更长时间。有什么方法可以防止这样的问题吗?随着这个功能进入成千上万,它或多或少只会因为需要多长时间而停止。

4 个答案:

答案 0 :(得分:0)

首先,对列表进行排序。

然后在列表中启动两个游标,两个游标在两端。在循环中,将游标下的两个值相加。如果它小于你想要的总数,则将左(较小)光标向右推进一步(“较大”方向。)如果总和较大,则将右(较小)光标向前推进一步。

如果有一对总和达到你想要的总和,就可以找到它。排序列表需要O(n log n)时间,并且O(n)时间来运行游标循环。总的来说,它是O(n log n),希望能够快速满足您的需求。

修改

实际上,有一个线性时间,线性空间算法来做到这一点。假设您的目标号码为k。对于列表中的每个整数i,将k - i插入哈希集。然后检查集合中是否已i。如果是,则必须是因为k - i之前已在列表中遇到过。这可能是@SpiderPig暗示的算法。

答案 1 :(得分:0)

这是对整数列表进行排序和二进制搜索的基本实现。

   import  java.util.ArrayList;
   import  java.util.Arrays;
   import  java.util.Collections;
/**
   <P>{@code java OrderIntListXmpl}</P>
 **/
public class OrderIntListXmpl  {
   public static final void main(String[] igno_red)  {
      int[] aiNums = new int[] {1, 11, 29, 12, 13, 19, 7, 2, 6, 16, 10, 15, 112, 18, 20, 3, 8, 5, 9, 14};

      System.out.println("Unsorted: " + Arrays.toString(aiNums));

      ArrayList<Integer> alNums = new ArrayList<Integer>(aiNums.length);
      for(int i : aiNums)  {
         alNums.add(i);
      }
      Collections.sort(alNums);

      System.out.println("Sorted: " + Arrays.toString(alNums.toArray()));

      int ixOf12 = Collections.<Integer>binarySearch(alNums, 12);

      System.out.println("Index of number 12: " + ixOf12);
   }
}

输出:

[C:\java_code\]java OrderIntListXmpl
Unsorted: [1, 11, 29, 12, 13, 19, 7, 2, 6, 16, 10, 15, 112, 18, 20, 3, 8, 5, 9, 14]
Sorted: [1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 29, 112]
Index of number 12: 10

sortbinarySearch

的Javadoc

答案 2 :(得分:0)

您可以尝试从普林斯顿教授Robert Segwick修改此example。它找到两个总和为0的数字。

有两个算法,一个是你使用Brute force和O(n2)。另一个nLog(n)跟随排序并否定另一个数字example

答案 3 :(得分:0)

为了尽可能快地使用数组。 这是一个例子。

class Primes {
    static int[] primeSieve(int max) {
        boolean[] sieve = new boolean[max];
        for(int i = 2; i < sieve.length; i++) {
            sieve[i] = true;
        }
        int prime = 2;
        while(prime*prime < max) {
            for(int i = prime*2; i < max; i += prime) {
                sieve[i] = false;
            }
            prime++;
            while(!sieve[prime]) prime++;
        }
        int primesSize = 0;
        for(int i = 0; i < max; i++) {
            if(sieve[i]) primesSize++;
        }
        int[] primes = new int[primesSize];
        for(int i = 0, j = 0; i < max; i++) {
            if(sieve[i]) primes[j++] = i;
        }
        return primes;
    }

    static boolean isSummable(int num, int[] primes) {
        for(int i = 0; i < primes.length && primes[i] < num; i++) {
            int j = num-primes[i];
            int index = java.util.Arrays.binarySearch(primes, j);
            if(index >= 0) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        int[] primes = primeSieve(1000000);
        System.out.println(primes.length);

        System.out.println(isSummable(575210, primes));
    }
}