Повысить эффективность вложенного цикла и ввести значение xor индексной строки, умноженное на индекс столбца, в массив, используя вложенный цикл?

#java #arrays #loops #nested-loops #xor

#java #массивы #циклы #вложенные циклы #xor

Вопрос:

Я пишу этот фрагмент кода, который проходит через вложенный массив и вводит значение xor индексной строки, умноженное на индекс столбца. Обычный цикл работает, но я хочу повысить эффективность цикла, чтобы не было проблем с кучей, когда я пытаюсь запустить его несколько раз с большими числами. вот обычный код цикла, который работает-

 long[][] ar= new long[(int)m][(int) n];
long m=8,n=5;
        long k =1,newp=100;
        long sum=0,sum1=0;
        for(long i=0; i< ar.length;i  ){
          for(long j=0;j<ar[0].length;j  ){//time received
             ar[(int) i][(int) j]= i ^ j;
             sum =ar[(int) i][(int) j];
  

вот моя попытка более эффективного цикла-

 long m=8,n=5;
        long[][] ar= new long[(int)m][(int) n];
        long sum1=0;
        for(long i: ar){
          for(long j[0]:ar){//time received
             ar[j][i]= (i ^ j);
             sum =ar[i][j];
}
}

  

вложенный цикл, похоже, работает, но массив, похоже, не получает переменные, а также сумму типа integer / long . помощь будет оценена. Кроме того, как я должен изменить вычисление xor, чтобы оно было правильным —i ^ j
трассировка стека:

 java.lang.OutOfMemoryError: Java heap space
    at Immortal.elderAge(Immortal.java:6)
    at ImmortalTest.example(ImmortalTest.java:19)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:40)
    at org.junit.vintage.engine.VintageTestEngine$$Lambda$212/0x00000008400d9c40.accept(Unknown Source)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
  

Комментарии:

1. 1. Второй фрагмент кода не компилируется — как вы ожидаете применить XOR к длинному значению j и к массиву i ? как i предполагается, что массив будет преобразован int и использован в качестве индекса? 2. В первом фрагменте кода m и n объявляются после использования в объявлении массива; также нет необходимости использовать long for m, n, i, j , поскольку длины и индексы массива int

2. Как говорит Алекс, код даже не компилируется. Также индекс массива не может быть длинным, просто int , как вы можете видеть по вашей собственной потребности в приведении. Почему вы используете longs для переменных индекса? Используйте оригинальный метод вместо for-each .

3. ОК. как мне исправить код, вложенный код, потому что в исходном коде есть ошибки кучи, когда используются большие числа, поэтому у меня есть long вместо целого числа. итак, как мне правильно изменить цикл?

4. @GilCaplan, если вы применяете XOR к int операндам, кажется излишним сохранять результат в 2D-массиве long . Однако, даже с int диапазоном, если вы попытаетесь использовать Integer.MAX_VALUE для обоих m , и n сомнительно, что ваша машина имеет ОЗУ ~ 2 ^ 64 байта. Насколько велики ваши большие числа?

5. Не могли бы вы, пожалуйста, показать нам всю трассировку стека?

Ответ №1:

Можно немного оптимизировать заполнение 2D-массива, принимая во внимание, что XOR является коммутативной операцией, то есть x ^ y == y ^ x .

Таким образом, для «квадратной» части массива (while i и j приведены ниже N = Math.min(m, n) ) следует рассматривать «треугольную» часть, исключая главную диагональ, которая будет заполнена 0 (потому x ^ x == 0 что ). Таким образом, вместо N 2 операций он будет принимать N * (N - 1) / 2 операции.

Для оставшейся части (более минуты) результаты XOR должны вычисляться, как и раньше.

 int min;
int max;
boolean moreRows;

if (m > n) {
    min = n;
    max = m;
    moreRows = true;
} else {
    min = m;
    moreRows = false;
    max = n;
}
int sum = 0;
int[][] ar2 = new int[m][n];
// square part
for (int i = 0; i < min; i  ) {
    for (int j = 0; j < i; j  ) {
        int t = i ^ j;
        ar2[i][j] = ar2[j][i] = t;
        sum  = 2 * t;
    }
}
for (int i = min; i < max; i  ) {
    for (int j = 0; j < min; j  ) {
        int t = i ^ j;
        sum  = t;
        if (moreRows) {
            ar2[i][j] = t;
        } else {
            ar2[j][i] = t;
        }
    }
}
for (int[] row: ar2) {
    System.out.println(Arrays.toString(row));
}

System.out.println("sum: "   sum);
  

Вывод для m = 5 , n = 8 :

 [0, 1, 2, 3, 4, 5, 6, 7]
[1, 0, 3, 2, 5, 4, 7, 6]
[2, 3, 0, 1, 6, 7, 4, 5]
[3, 2, 1, 0, 7, 6, 5, 4]
[4, 5, 6, 7, 0, 1, 2, 3]
sum: 140
  

Комментарии:

1. эй, я не уверен на 100%, как это сделать — допустим, я хочу перейти на следующий уровень, я хочу взять заданный k (допустим, k = 1), он берет из каждого индекса в нашем массиве индекс и выполняет xor — k, но только если эточисло больше или равно k — поэтому, если индекс равен 0, ничего не происходит (в примере, где k = 1). дайте мне знать, если сможете помочь. Спасибо

2. Кажется, в этом случае вводится другой параметр k , и значение, записанное в массив, вычисляется следующим образом: int xor = i ^ j; ar2[i][j] = ar2[j][i] = xor - (xor >= k ? k : 0); с использованием троичного оператора.

3. (xor >= k ? k : 0) не могли бы вы объяснить, что делает этот фрагмент кода, пожалуйста. Я попытался вставить это в код, но не увидел, что это имеет какое-либо значение, будет ли эта строка работать с любым значением переменной k? Спасибо

4. bool_operand ? true_arg : false_arg является ли тернарный оператор : краткая форма if-else оператора, которая может использоваться в выражениях. Для k = 4 и исправления в обеих частях значение sum становится 60.