循环i和j,其中i!= j

时间:2014-03-01 01:46:55

标签: java math combinations combinatorics

例如,我需要获得2值数组的所有组合,数字为{0,1,2},其中这两个数字不相同。  我得到了

0 1
0 2
1 0
1 2
2 0 
2 1

我忽略了

0 0
1 1
2 2

现在我用

  for (int i= 0; i < L ; i++) {
                for (int j = 0; j < L; j++) {
                    if (i!= j) {

但它很慢? 对此有何解决方案? L将是> 4000。

我在做的是找到分裂矩阵到4个子矩阵的每个组合

示例:

 3 | 0   2  -8  -8
 5 | 3   2   2   3
 2 | 5   2   1   4
 -------------------
 3   4  -1 |  4  2
-3   6   2 |  4  3

并使用sum-table计算它们的总和。

相关问题:Split matrix into 4 sub-matrices with lowest difference between their sum

因此对于matix我有一条水平线和两条垂直线,我计算4个矩阵的总和,但是两条垂直线不应该包含一条大的垂直线,所以i!= j。

UPDATE 1 对的顺序是相关的

4 个答案:

答案 0 :(得分:7)

您可以通过以下方式改善效果:

for (int i= 0; i < L ; i++) {
                for (int j = i + 1 ; j < L; j++) {
System.out.println.(i + " " + j + "\n" + j + " " + i);
}}

答案 1 :(得分:1)

可能能够从

中获益
for (int i= 0; i < L ; ++i) {
  int j=0;
  for (; j < i; ++j) {
  }
  for (++j; j < L; ++j) {
  }
}

避免在您仍在测试L时测试i。我也已经切换到预增量 - 因为你没有使用结果它可能在优化器完成之后没有任何区别,但是后增量在概念上是一个更多复杂的操作,除非碰巧有指令集支持。

如果您可以更改报告结果的顺序,则会更快:

int L1=L-1;
for (int i=L1; i >=0 ; --i) {
  int j=L1;
  for (; j > i; --j) {
  }
  for (--j; j >=0; --j) {
  }
}

针对大多数值进行测试需要减法。对零进行测试不会;加载值时,它“免费”发生。事实上,你可以进一步改进它:

int L1=L-1, i=L1;
do {
  int j=L1;
  do {
  } while(--j>i);
  while(--j>=0)
  {
  }
} while(--i >= 0);

这避免了冗余的初始测试。 (注意,如果我是0,你仍然需要在第二个循环的顶部进行测试。)

然而,事实上,循环开销是你的问题中最少的; System.out.println()调用将比循环控制消耗更多的周期。

答案 2 :(得分:1)

如果对的顺序相关(例如,您希望将{1, 2}{2, 1}视为不同),则可以在此级别获得显着的加速。

如果对的顺序无关紧要(例如,您已考虑{1, 2},则可以跳过{2, 1}),那么@ goten的答案会为您提供2倍加速的因子。 更新问题已更新,以确认订单相关...所以@ goten的解决方案不适用。

微观优化它不太可能获得显着的加速;例如把它变成一个while循环等等.JIT编译器最有可能在幕后进行等效的优化。

如果您想要更好的加速,则需要更改整体算法,以便不需要考虑这么多组合。这是否可行将取决于您的问题。

要考虑的另一种方法是并行处理组合。但是,这只有在您拥有多个核心时才有用......并且您的问题/算法适合并行化。

更新 - 您的问题(根据更新的问题)看起来应该适合并行化,但您可能需要进行一些仔细调整以最大限度地减少影响访问大型共享输入数组时的内存争用。

答案 3 :(得分:1)

对于给定的极点,c为极点的大小

 long[] radky = new long[x];
        long cisloRadku = 0;


    long min = 0;
    int q;
    int radek = 0;

    for (q = 0; q < (x); q++) {
        for (int j = 0; j < x; j++) {
            radky[q] += pole[q][j];

        }

        cisloRadku += radky[q];
    }


    long hodnota1 = 0;
    long hodnota2 = 0;

    for (int i = 0; i < (x - 1); i++) {
        hodnota1 += radky[i];
        hodnota2 = cisloRadku - hodnota1;


        long druheMin = hodnota1 - hodnota2;

        if (druheMin < 0) {
            druheMin = druheMin * (-1);
        }
        if (i == 0) {
            min = druheMin;
        }
        if (min > druheMin) {
            min = druheMin;
            radek = i;
        }
    }

    long[][] poleHorni = new long[radek + 1][x];
    long[][] poleDolni = new long[x - (radek + 1)][x];


    for (int i = 0; i < (radek + 1); i++) {
        for (int j = 0; j < x; j++) {
            poleHorni[i][j] = pole[i][j];

        }

    }


    long[] soucetHornich = new long[x];
    long soucetSlopucuUp = 0;
    for (int k = 0; k < x; k++) {
        for (int j = 0; j < radek + 1; j++) {
            soucetHornich[k] += poleHorni[j][k];
        }

        soucetSlopucuUp += soucetHornich[k];
    }


    long cislo1 = 0;
    long cislo2;
    int sloupec = 0;
    long min2 = 0;
    for (int i = 0; i < (x - 1); i++) {
        cislo1 += soucetHornich[i];
        cislo2 = soucetSlopucuUp - cislo1;

        long druheMin2 = cislo1 - cislo2;


        if (druheMin2 < 0) {
            druheMin2 = druheMin2 * (-1);
        }
        if (i == 0) {
            min2 = druheMin2;
            vysledky[0] = cislo1;
            vysledky[1] = cislo2;
        }
        if (min2 > druheMin2) {
            min2 = druheMin2;
            sloupec = i;
            vysledky[0] = cislo1;
            vysledky[1] = cislo2;
        }
    }


    int a = 0;
    int b = 0;

    for (int i = (radek + 1); i < (x); i++) {
        for (int j = 0; j < x; j++) {
            poleDolni[a][b] = pole[i][j];

            b++;
        }
        b = 0;
        a++;

    }


    long[] soucetDolnich = new long[x];
    long soucetSlopucuDown = 0;

    for (int k = 0; k < x; k++) {
        for (int j = 0; j < (x - (radek + 1)); j++) {
            soucetDolnich[k] += poleDolni[j][k];
        }

        soucetSlopucuDown += soucetDolnich[k];
    }

    long cislo1A = 0;
    long cislo2A;
    long min2A = 0;
    for (int i = 0; i < (x - 1); i++) {
        cislo1A += soucetDolnich[i];
        cislo2A = soucetSlopucuDown - cislo1A;

        long druheMin2A = cislo1A - cislo2A;


        if (druheMin2A < 0) {
            druheMin2A = druheMin2A * (-1);
        }
        if (i == 0) {
            min2A = druheMin2A;
            vysledky[2] = cislo1A;
            vysledky[3] = cislo2A;
        }
        if (min2A > druheMin2A) {
            min2A = druheMin2A;

            vysledky[2] = cislo1A;
            vysledky[3] = cislo2A;
        }



    long[] vyslRozdil = new long[6];
    vyslRozdil[0] = vysledky[0] - vysledky[1];
    vyslRozdil[1] = vysledky[0] - vysledky[2];
    vyslRozdil[2] = vysledky[0] - vysledky[3];
    vyslRozdil[3] = vysledky[1] - vysledky[2];
    vyslRozdil[4] = vysledky[1] - vysledky[3];
    vyslRozdil[5] = vysledky[2] - vysledky[3];
    long max = 0;
    long max2;

    for (int i = 0; i < 6; i++) {
        if (vyslRozdil[i] < 0) {
            vyslRozdil[i] *= -1;
        }
        max2 = vyslRozdil[i];
        if (i == 0) {
            max = max2;
        }
        if (max < max2) {
            max = max2;
        }
    }

    System.out.println(max);