如何提高此算法的运行时复杂度?

时间:2015-10-02 22:13:09

标签: java time-complexity

public static boolean PP(int[] A){

    int n = A.length;

    for(int i = 0; i < (n-1); i++){             //finds one value in the array
        for(int j = (i+1); j < n; j++){         //compares all the other values with that one value
            if (A[i] * A[j] == 225){
                return true;
            }
        }
    }
    return false;               //returns false if it goes through the entire for loop without returning true
}

此代码采用数组并尝试找到两个乘以225的数字。如果找到两个数字则返回true。目前运行时间为O(n ^ 2),但我想获得更快的运行时间,如O(nlogn)或O(n)。那么如何减少这个的运行时间呢?

4 个答案:

答案 0 :(得分:4)

这是一个O(n)解决方案。您可以使用HashMap<Integer, Integer>。插入(累计)来自a的所有元素及其在HashMap<Integer, Integer> c

中的计数
for (int e : a) {
     if (225 % e == 0) {
         int t = 225/e;
         if (c.containsKey(t)) {
             if (t == e) {
                 if c.get(t) >= 2)
                     return true;
             }
             else
                 return true;
         }
     }
}  
return false;

答案 1 :(得分:3)

您可以对数组进行排序,然后迭代每个元素并使用二进制搜索找到合适的元素。时间复杂度:O(N * logN):

public static boolean PP(int[] A){

    int N = A.length;

    Arrays.sort(A);
    for (int i = 0;i<N-2;i++){
        int a = A[i];
        if (a == 0)
            continue;
        int seek = 225 / a;
        int res = Arrays.binarySearch(A, i+1,N,seek);
        if(res>0 && A[res]*a==225)
            return true;
    }
    return false;               //returns false if it goes through the entire for loop without returning true
}

答案 2 :(得分:2)

所以你只想在一个数组中找到2个值,乘以时得到225,并返回true并在找到时立即打破循环。

通过A迭代,并按每个值除以225。 检查hashset是否包含A [i],如果包含,则返回true。 否则,将除法结果存储在哈希集中。 迭代完你的数组后返回false。

这应该有效,因为A * B = 225B = 225 / A

这样,如果我们知道A,我们知道&#34; B&#34;结果是真的。

通过将A存储在一个哈希集中,你遇到了一个B,其中225 / B已经在哈希集中(可以在O(1)中完成),那么你知道你有A * B = 225对

通过使用哈希集,您可以将一个值与O(1)中的其余值进行比较,使您能够将数组中的所有值与O(n)时间内的每个其他值进行比较。

Set<Double> mySet = new HashSet<Double>();
for (int i = 0; i < N; i++) {
    double val = 225 / (double) A[i];
    if (mySet.contains(val)) {
        return true;
    }
    if (!mySet.contains((Double)A[i]) {
        mySet.add((Double)A[i]);
    }
}
return false;

现在请注意,我没有先将所有值放入hashset中并比较所有内容。我在添加到hashset时进行比较(这仍然会确保您将所有值相互比较一次!)见下图:

// The below represents the above algo on an array with 10 elements.
// The values 0 ~ 9 are the index.
// The left row is my insert, and top row is my "compare." 
// Every intersection "[]" means that the value has been compared to each other.

   0  1  2  3  4  5  6  7  8  9
0     [] [] [] [] [] [] [] [] []
1        [] [] [] [] [] [] [] []
2           [] [] [] [] [] [] []
3              [] [] [] [] [] []
4                 [] [] [] [] []
5                    [] [] [] []
6                       [] [] []
7                          [] []
8                             []
9 

// You can see that every value actually compares to each other (except
// for itself. More on this below)

我没有先将所有内容添加到hashset中,然后使用&#34;比较我们添加&#34;方法,因为它有可能意外错误的空间:

如果您的数组中有一个值15的单个实例,您将以这种方式比较15,导致您获得225并返回true,但您实际上可能需要&#34; unique&# 34;对。 (现在这取决于你要解决的问题)

如果您的数组只是{ 15 },您是否想要返回true

如果您的答案是肯定的,请切换代码以先添加,然后再进行比较:

Set<Double> mySet = new HashSet<Double>();
for (int i = 0; i < N; i++) {
    double val = 225 / (double) A[i];
    if (!mySet.contains((Double)A[i]) {
        mySet.add((Double)A[i]);
    }
    if (mySet.contains(val)) {
        return true;
    }
}
return false;

答案 3 :(得分:0)

  1. 创建包含int B[]的{​​{1}}(丢弃不完美除数的元素)
  2. 订单A和B - O(n登录)
  3. 在两个有序数组中搜索公共元素 - O(n)