【问题标题】:Improve time complexity of this algorithm?提高这个算法的时间复杂度?
【发布时间】:2017-02-18 15:10:49
【问题描述】:

我创建了这个算法,它所做的就是找到具有相同乘积的整数对,并且对中的整数必须不同。产品不得超过1024。这是我能想到的最简单的方法,有没有办法可以提高这个算法的效率和时间复杂度?

谢谢

import java.util.ArrayList;

public class Pairs {

    public static void main(String [] args){

        int nums[] = new int[1024];
        for(int i = 1;i<=1024;i++){
            nums[i-1] = i;
        }
        findPairs(nums);

    }

    static void findPairs(int [] nums){


        ArrayList<IntPair> pairs = new ArrayList<IntPair>();
        ArrayList<Products> products = new ArrayList<Products>();

        IntPair tempObject;
        Products tempProduct;
        int tempMultiplication = 0;

        for(int i =0;i<nums.length;i++){

            for(int j=0;j<nums.length;j++){

                tempObject = new IntPair(nums[i],nums[j]);
                pairs.add(tempObject);

                }


            }

        for(IntPair p:pairs){
            tempProduct = new Products(p.x,p.y);

            if(tempProduct.product <= 1024){
                products.add(tempProduct);
            }


        }


        for(int i = 0;i<products.size();i++){

            tempMultiplication = products.get(i).product;

            for(int j = 0;j<products.size();j++){

                 if(products.get(j).product == tempMultiplication)
                 {
                    if(products.get(i).x == products.get(j).x || products.get(i).y == products.get(j).y) {


                     }
                    else if (products.get(i).x == products.get(j).y || products.get(j).x == products.get(j).y || products.get(i).x == products.get(i).y){


                    }
                     else{
                         System.out.println("Matching pair found:("+ products.get(i).x + ","+products.get(i).y+")"  + "("+ products.get(j).x + ","+products.get(j).y+")" );
                     }


                 }


            }

        }


    }


}

【问题讨论】:

  • 将所有(不同的)整数配对,将它们放入Map&lt;Integer, List&lt;Pair&gt;&gt;,其中键是产品,值是与该产品的配对列表。
  • 这里有很多需要改进的地方。使用 set/map 可以避免大量迭代(另请注意 j=0 应该是 j=i+1)
  • 你无法提高最坏情况的时间复杂度:如果你正在寻找成对的东西,它至少必须是O(n^2)。你所能做的就是减少乘法常数。
  • 所以基本上我创建的这个算法没有那么糟糕吧?
  • @Jack 你能解释一下为什么我需要使用 j = i+1 而不是 j = 0 吗?谢谢你的回答

标签: java algorithm time complexity-theory


【解决方案1】:

您无法提高算法的时间复杂性。它是O(n^2),如果您要比较输入中的所有对,就可以做到这一点。

但这并不是说您无法改善运行时间。并非所有O(n^2) 算法都同样出色;你可以通过让它做更少的工作来让它运行得更快;在这种情况下,这基本上意味着跳过检查乘积不能相等的数字。

将对放入具有相等乘积的桶中:

Map<Integer, List<int[]>> map = new HashMap<>();
for (int i = 0; i < nums.length; ++i) {
  for (int j = i+1; j < nums.length; ++j) {
    if (nums[i] == nums[j] || nums[i]*nums[j] > 1024) continue;

    map.computeIfAbsent(nums[i]*nums[j], ArrayList::new)
        .add(new int[] {nums[i], nums[j]});
  }
}

然后只需迭代每个桶中的所有对:

for (List<int[]> list : map.values()) {
  for (int i = 0; i < list.size(); ++i) {
    for (int j = 1; j < list.size(); ++j) {
      System.out.printf(
          "Matching pair found: %s %s%n",
          Arrays.toString(list.get(i)),
          Arrays.toString(list.get(j)));
    }
  }
}

在最坏的情况下,这仍然是O(n^2),即所有数对具有相等的乘积,这意味着对具有相等乘积的对的迭代只是迭代所有对。不过,我怀疑这实际上是否可行,但并非所有数字都相等,而检查这对中的数字是否不同是禁止的。

您可以先对nums 进行排序,然后在nums[i]*nums[j] &gt; 1024 上中断一次顶部内循环,而不是继续,这样可以节省一点时间;这取决于nums 有多大,是否值得对其进行排序(如果您不想更改输入数组,可能会复制它)。

【讨论】:

  • 我对算法here 有类似的问题。在将其放入地图之前尝试制作固定大小的字符串。我不确定我是否做对了,所以想和你核实一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
相关资源
最近更新 更多