Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从数字列表生成所有唯一对,n选择2_Java_Algorithm_Math_Combinations_Combinatorics - Fatal编程技术网

Java 从数字列表生成所有唯一对,n选择2

Java 从数字列表生成所有唯一对,n选择2,java,algorithm,math,combinations,combinatorics,Java,Algorithm,Math,Combinations,Combinatorics,我有一个元素列表(比如整数),我需要进行所有可能的2对比较。我的方法是O(n^2),我想知道是否有更快的方法。这是我的java实现 public class Pair { public int x, y; public Pair(int x, int y) { this.x = x; this.y = y; } } public List<Pair> getAllPairs(List<Integer> numbers) { List<Pair>

我有一个元素列表(比如整数),我需要进行所有可能的2对比较。我的方法是O(n^2),我想知道是否有更快的方法。这是我的java实现

public class Pair {
 public int x, y;
 public Pair(int x, int y) {
  this.x = x;
  this.y = y;
 }
}

public List<Pair> getAllPairs(List<Integer> numbers) {
 List<Pair> pairs = new ArrayList<Pair>();
 int total = numbers.size();
 for(int i=0; i < total; i++) {
  int num1 = numbers.get(i).intValue();
  for(int j=i+1; j < total; j++) {
   int num2 = numbers.get(j).intValue();
   pairs.add(new Pair(num1,num2));
  }
 }
 return pairs;
}
公共类对{
公共整数x,y;
公共对(整数x,整数y){
这个.x=x;
这个。y=y;
}
}
公共列表getAllPairs(列表编号){
列表对=新的ArrayList();
int total=numbers.size();
对于(int i=0;i
请注意,我不允许自配对,因此应该有((n(n+1))/2)-n个可能的配对。我现在做的很好,但是随着n的增加,我花了很长时间才得到这对。有没有办法把上面的O(n^2)算法变成次二次的?感谢您的帮助

顺便说一句,我也尝试了下面的算法,但当我以经验为基准测试时,它的性能比我上面的算法差。我曾认为,通过避免内部循环,这将加快速度。下面的算法不应该更快吗?我会认为是O(n)?如果没有,请解释并让我知道。谢谢

public List<Pair> getAllPairs(List<Integer> numbers) {
 int n = list.size();
 int i = 0;
 int j = i + 1;
 while(true) {
  int num1 = list.get(i);
  int num2 = list.get(j);
  pairs.add(new Pair(num1,num2));

  j++;

  if(j >= n) {
   i++;
   j = i + 1;
  }

  if(i >= n - 1) {
   break;
  }
 }
}
公共列表getAllPairs(列表编号){
int n=list.size();
int i=0;
int j=i+1;
while(true){
int num1=list.get(i);
int num2=list.get(j);
添加(新对(num1,num2));
j++;
如果(j>=n){
i++;
j=i+1;
}
如果(i>=n-1){
打破
}
}
}

嗯,你不能,对吧


结果是一个包含
n*(n-1)/2
元素的列表,无论这些元素是什么,只要填充这个列表(比如用零)就需要
O(n^2)
时间,因为
n*(n-1)/2=O(n^2)

您不能将其设置为次二次曲面,因为正如您所说的——输出本身就是二次曲面——要创建它,您至少需要在输出中使用
#元素

但是,你可以做一些“作弊”动态创建你的列表
您可以创建一个实现的类
CombinationsGetter
,并实现其。这样,您就可以动态地迭代元素,而无需先创建列表,这可能会减少应用程序的延迟

注意:它仍然是二次曲线!动态生成列表的时间将在多个操作之间分配


编辑: 另一种比原始方法更快的解决方案是多线程。
创建几个线程,每个线程将获得自己的数据“切片”——并生成相关的线程对,并创建自己的部分列表。
稍后-您可以使用将这些不同的列表转换为一个列表。
注意:虽然复杂性仍然是
O(n^2)
,但它可能要快得多-因为成对的创建是并行完成的,而且
ArrayList.addAll()
的实现比简单的逐个插入元素要高效得多

EDIT2: 您的第二个代码仍然是
O(n^2)
,即使它是一个“单循环”-循环本身将重复
O(n^2)
次。查看变量
i
。只有当
j==n
时,它才会增加,当它这样做时,它会将
j
减小到
i+1
。因此,它将导致
n+(n-1)+…+1
iterations,这是,让我们回到
O(n^2)
预期的状态


我们不可能比O(n^2)更好,因为我们正在尝试创建O(n^2)个不同的
对象。

如果我能找到一种方法来避免内部循环,这至少在理论上会使它更快吗?我试着用一个单循环(while循环),事实上,这需要更长的时间。顺便说一句,最坏情况下的运行时间复杂性不是由算法和输入的实际步骤定义的,而不是由输出定义的吗?实际上。。。不不管你有多少个内部循环;重要的是迭代次数。即使你用一个循环来编写它,这个循环也必须有
n*(n-1)/2次
迭代,所以它的复杂性是相同的。我发布了一个不同的版本来获得这些对。它只有一个循环。你能帮我回答上面的问题吗?这是第二个算法O(n)?我同意你的建议(动态创建和多线程)。动态创建不会太难实现,但多线程可能会更快,但代价是代码/编码不够优雅。如果我开始传递一个巨大的列表(我想这样做的方式),它可能会更慢。@JaneWayne:你不可能比
O(n^2)
更好地创建所有需要的对。我编辑了答案,对您的第二个实现进行了具体分析,但无论您做什么—创建
O(n^2)
Pair
对象,都需要
O(n^2)
ops。谢谢。我一直在努力找一本关于算法分析的好书(不是大多数大学用的那种大的精装书)。如果你有任何建议,请告诉我。