Подтвердить что ты не робот

Диагональное заполнение массива 2d

1 2 3
4 5 6
7 8 9

это мой обычный массив, но мне нужно сделать его по диагонали следующим образом

1 2 4
3 5 7
6 8 9

Это очень глупый способ заставить его работать, но даже он не работает, потому что я не могу найти элементы второго столбца.

for (i = 0; i < arr.length; ++i) {
    for (n = 0; n < arr[0].length; ++n) {
        if (i == 0 && n == 0){
            arr[i][n] = 0;
        } else if (i == 0 && n == 1) {
            arr[i][n] = 2;
        } else if (i == 1 && n == 0) {
            arr[i][n] = 3;
        } else if (n == 0) {
            arr[i][n] = arr[i - 1][n] - arr[i - 2][n] + 1 + arr[i - 1][n];
        } else {
            arr[i][n] = arr[i][n - 1] - arr[i][n - 2] + 1 + arr[i][n - 1];
        }
    }
}
4b9b3361

Ответ 1

Хорошо, если вы должны были перечислять индексы для этого шаблона заполнения, вы получили бы

0,0
1,0
0,1
2,0
1,1
0,2
2,1
1,2
2,2

Итак, вам нужно выполнить итерацию по общим двум индексам. То есть суммарная добавка. Как вы можете видеть, 0,0 итоговые значения 0, 1,0 и 0,1 всего 1 и т.д. Дайте нам что-то вроде этого:

0 1 2
1 2 3
2 3 4

Чтобы выполнить итерацию в этом диагональном шаблоне, мы можем сделать следующее:

// set up your matrix, any size and shape (MxN) is fine, but jagged arrays will break
int[][] matrix = {{0,0,0},{0,0,0},{0,0,0}};

// number is the value we will put in each position of the matrix
int number = 1;

// iterate while number is less than or equal to the total number of positions
// in the matrix. So, for a 3x3 matrix, 9. (this is why the code won't work for
// jagged arrays)
for (int i = 0; number <= matrix.length * matrix[0].length; i++) {
    // start each diagonal at the top row and from the right
    int row = 0;
    int col = i;

    do {
        // make sure row and length are within the bounds of the matrix
        if (row < matrix.length && col < matrix[row].length) {
            matrix[row][col] = number;
            number++;
        }

        // we decrement col while incrementing row in order to traverse down and left
        row++;
        col--;
    } while (row >= 0);
}

Обратите внимание, что хотя эта реализация будет работать для всех размеров (и форм) матрицы, она не будет настолько эффективной, насколько это возможно. Где n - matrix.length (предполагая квадратную матрицу), эта реализация является оптимальным алгоритмом класса O(n^2) в большой нотации O; однако он эффективно выполняет итерации 2*n^2, тогда как оптимальное решение будет выполнять только n^2.

Ответ 2

Вы хотите добиться чего-то вроде этого:

1 2 4 7
3 5 8 B
6 9 C E
A D F G

В сетке размера NxN для каждой точки (x, y) в сетке вы можете определить значение, подобное этому (все еще нужны некоторые исправления для смещения в 0, см. окончательную формулу):

  • если вы находитесь в верхней левой половине, вычислите область треугольника, которая находится выше и слева от вас, и добавьте расстояние от верхней части

  • если вы находитесь в нижней правой половине (или посередине), вычислите область треугольника ниже и справа от вас, добавьте свое расстояние снизу и вычтите из всей области

Попробуем это как формулу:

int N = 4; int[][] v = new[N][N];
for(int y = 0; y < N; y++) for(int x = 0; x < N; x++)
v[x][y] = ( x + y < N ) ?
    ( ( x + y + 1 ) * ( x + y ) / 2 + y + 1 ) :
    ( N * N + 1 - ( N - y ) - ( 2 * N - x - y - 1 ) * ( 2 * N - x - y - 2 ) / 2 );

Я не знаю, какая это сложность, но эксперты могут уверенно подтвердить, что это O (N ^ 2)? Кроме того, если у него есть классное имя, например динамический код, сообщите мне об этом!

Преимущество, которое я вижу здесь, заключается в том, что вам не нужно прыгать вокруг памяти и заполнять все поля одним линейным прогоном через память. Также использование его как независимой от истории формулы может быть оптимизировано компилятором или позволит улучшить параллелизацию. Если у вас была машина с N ^ 2 единицами, они могли бы вычислить всю матрицу за одну операцию.

Ответ 3

Диагональ матрицы M по N с форматированием форматированного массива

Учитывая, что многие из этих ответов уже рассмотрели основные массивы N на N, а некоторые из них довольно эффективны, я пошел вперед и сделал более надежную версию, которая обрабатывает массивы M by N вместе с красивым отформатированным принтером для ваше собственное наслаждение/мазохистское наблюдение.

Эффективность этого метода равна O (N ^ 2). Формат принтера - O (N ^ 2).

код

Главная

Вы можете установить любые строки и столбцы, которые вы хотите, при условии положительных целых значений.

public static void main(String[] args) {
    //create an M x N array
    int rows = 20;  
    int columns = 11;
    int[][] testData = new int[rows][columns];

    //iteratively add numbers
    int counter = 0;
    for(int i = 0; i < rows; i++) {
        for(int j = 0; j < columns; j++)  {
            testData[i][j] = ++counter;
        }
    }

    //print our test array
    printArray(testData);
    System.out.println("");
    //print our diagonal array
    printArray(diagonal(testData));
}

Печать 2-мерного массива

Этот метод работает специально для этого примера, определяя количество записей с использованием M x N, а затем подсчитывая цифры. Если вы хотите, скажем, отобразить любой размер массива на основе самого длинного элемента в массиве, вы можете легко адаптировать этот код для этого. Достойный вызов, который лучше всего отводится читателю. O (N ^ 2) для этого, но из-за необходимости искать массив для наибольшего значения, тот, который принимает самую большую цифру, по своей природе потребует другого O (N ^ 2) для поиска.

static void printArray(int[][] array) {
    //get number of digits
    int count = array.length * array[0].length;
    //get power of function
    int power;

    //probably the only time I'd ever end a for loop in a semicolon
    //this gives us the number of digits we need
    //You could also use logs I guess but I'm not a math guy
    for(power = 0; count / Math.pow(10, power) > 1; power++);

    for(int i = 0; i < array.length; i++){
        System.out.print("{");
        for(int j = 0; j < array[0].length; j++){
           //Let say Power is 0. That means we have a single-digit number, so we need
           // +1 for the single digit. I throw in 2 to make it extra wide
           System.out.print(String.format("%" + Integer.toString(power + 2) 
                   + "s", Integer.toString(array[i][j])));
        }
        System.out.println("}");
     }
}

Диагональный преобразователь

Там много краевых случаев для тестирования, когда мы учитываем M x N, поэтому я пошел вперед и, кажется, охватил все их. Не самый аккуратный, но, похоже, работает.

static int[][] diagonal(int[][] input) {
    //our array info 
    final int numRows = input.length;
    final int numColumns = input[0].length;
    int[][] result = new int[numRows][numColumns];

    //this is our mobile index which we will update as we go through 
    //as a result of certain situations
    int rowIndex = 0;
    int columnIndex = 0;
    //the cell we're currently filling in
    int currentRow = 0;
    int currentColumn = 0;
    for(int i = 0; i < numRows; i++) {
        for(int j = 0; j < numColumns; j++) {
            result[currentRow][currentColumn] = input[i][j];
            //if our current row is at the bottom of the grid, we should
            //check whether we should roll to top or come along
            //the right border
            if(currentRow == numRows - 1) {
                //if we have a wider graph, we want to reset row and
                //advance the column to cascade
                if(numRows < numColumns && columnIndex < numColumns - 1 ) {
                    //move current row down a line
                    currentRow = 0;
                    //reset columns to far right
                    currentColumn = ++columnIndex;
                }
                //if it a square graph, we can use rowIndex;
                else {
                    //move current row down a line
                    currentRow = ++rowIndex;
                    //reset columns to far right
                    currentColumn = numColumns - 1;
                }
            }
            //check if we've reached left side, happens before the 
            //top right corner is reached
            else if(currentColumn == 0) {
                //we can advance our column index to the right
                if(columnIndex < numColumns - 1) {
                    currentRow = rowIndex;                        
                    currentColumn = ++columnIndex;
                }
                //we're already far right so move down a row
                else {
                    currentColumn = columnIndex;
                    currentRow = ++rowIndex;
                }
            }
            //otherwise we go down and to the left diagonally
            else {
                currentRow++;
                currentColumn--;
            }

        }
    }
    return result;
}

Пример вывода

Input
{   1   2   3}
{   4   5   6}
{   7   8   9}
{  10  11  12}

Output
{   1   2   4}
{   3   5   7}
{   6   8  10}
{   9  11  12}


Input
{   1   2   3   4   5   6}
{   7   8   9  10  11  12}
{  13  14  15  16  17  18}
{  19  20  21  22  23  24}
{  25  26  27  28  29  30}
{  31  32  33  34  35  36}

Output
{   1   2   4   7  11  16}
{   3   5   8  12  17  22}
{   6   9  13  18  23  27}
{  10  14  19  24  28  31}
{  15  20  25  29  32  34}
{  21  26  30  33  35  36}

Input
{    1    2    3    4    5    6}
{    7    8    9   10   11   12}
{   13   14   15   16   17   18}
{   19   20   21   22   23   24}
{   25   26   27   28   29   30}
{   31   32   33   34   35   36}
{   37   38   39   40   41   42}
{   43   44   45   46   47   48}
{   49   50   51   52   53   54}
{   55   56   57   58   59   60}
{   61   62   63   64   65   66}
{   67   68   69   70   71   72}
{   73   74   75   76   77   78}
{   79   80   81   82   83   84}
{   85   86   87   88   89   90}
{   91   92   93   94   95   96}
{   97   98   99  100  101  102}
{  103  104  105  106  107  108}
{  109  110  111  112  113  114}
{  115  116  117  118  119  120}
{  121  122  123  124  125  126}
{  127  128  129  130  131  132}
{  133  134  135  136  137  138}
{  139  140  141  142  143  144}
{  145  146  147  148  149  150}

Output
{    1    2    4    7   11   16}
{    3    5    8   12   17   22}
{    6    9   13   18   23   28}
{   10   14   19   24   29   34}
{   15   20   25   30   35   40}
{   21   26   31   36   41   46}
{   27   32   37   42   47   52}
{   33   38   43   48   53   58}
{   39   44   49   54   59   64}
{   45   50   55   60   65   70}
{   51   56   61   66   71   76}
{   57   62   67   72   77   82}
{   63   68   73   78   83   88}
{   69   74   79   84   89   94}
{   75   80   85   90   95  100}
{   81   86   91   96  101  106}
{   87   92   97  102  107  112}
{   93   98  103  108  113  118}
{   99  104  109  114  119  124}
{  105  110  115  120  125  130}
{  111  116  121  126  131  136}
{  117  122  127  132  137  141}
{  123  128  133  138  142  145}
{  129  134  139  143  146  148}
{  135  140  144  147  149  150}

Ответ 4

Вам нужно сделать преобразование из индекса 0..n для x/y (от 0 до x * y) и вернуться к x/y из индекса...

public void toPos(int index){
    return...
}

public int toIndex(int x, int y){
    return...
}

Я оставил вам детали реализации.

Ответ 5

Интуиция Люка - хорошая - вы работаете с диагоналями внизу и слева. Другое замечание - длина диагонали: 1, 2, 3, 2, 1. Я также принимаю квадратную матрицу. Мессинг с вашими указателями может привести к следующему:

    int len = 1;
    int i = 1;
    while(len <= arr.length){
        //Fill this diagonal of length len
        for(int r = 0; r < len; r++){ 
            int c = (len - 1) - r;
            arr[r][c] = i;
            i++;
        }

        len++;
    }
    len--; len--;
    while(len > 0){
        //Fill this diagonal of length len
        for(int c = arr.length - 1; c > (arr.length - len - 1); c--){ 
            int r = arr.length - len + 2 - c;
            arr[r][c] = i;
            i++;
        }

        len--;
    }

    System.out.println(Arrays.deepToString(arr));

Ответ 6

Вот код, переведенный с here на Java и настроенный на вашу проблему.

int[][] convertToDiagonal(int[][] input) {
    int[][] output = new int[input.length][input.length];
    int i = 0, j = 0; // i counts rows, j counts columns

    int n = input.length;
    for (int slice = 0; slice < 2 * n - 1; slice++) {
        int z = slice < n ? 0 : slice - n + 1;
        for (int k = z; k <= slice - z; ++k) {
            // store slice value in current row
            output[i][j++] = input[k][slice - k];
        }
        // if we reached end of row, reset column counter, update row counter
        if(j == n) {
            j = 0;
            i++;
        }
    }
    return output;     
}

Input:

| 1 2 3 |
| 4 5 6 |
| 7 8 9 |

Вывод:

| 1 2 4 |
| 3 5 7 |
| 6 8 9 |

Нажмите здесь для запуска тестового кода

Ответ 7

Это простое решение динамического программирования (ish). Вы в основном учитесь на последнем сделанном вами ходу.

ПРИМЕЧАНИЕ: ЭТО А O(N^2) ALGOIRTHM

Initialize:

 int m = 4;
 int n = 4;
 int[][] array = new int[m][n];;
 for(int i = 0; i < 3; i++){
    for(int j = 0; j < 3; j++){
        array[i][j] = 0;
    }
 }

Работа:

array[0][0] = 1;
for(int i = 0; i < m; i++){
    if(i != 0){ array[i][0] = array[i-1][1]+1;} 
  // This is for the start of each row get 1+ the diagonal 
    for(int j = 1; j < n; j++){
        if(i == 0){
            array[i][j] = array[i][j-1]+j;
            // only for the first row, take the last element and add + row Count
        }else{
            if(i == m-1 && j == n -1){
               // This is only a check for the last element
                array[i][j] = array[i][j-1]+1;
                break;  
            } 
            // all middle elements: basically look for the diagonal up right.
            // if the diagonal up right is out of bounds then take +2 the 
            // prev element in that row
            array[i][j] = ((j+1) != (m)) ? array[i-1][j+1] +1: array[i][j-1]+2;
        }
    }
}

Печать решения:

 for(int i = 0; i < m; i++){
     for(int j = 0; j < n; j++){
        System.out.print(array[i][j]);
     }
     System.out.println("");
  }
 return 0;
}

Ответ 8

Вот полный рабочий код для вашей проблемы. Скопируйте и вставьте, если хотите

public class FillArray{
    public static void main (String[] args){


    int[][] array = {
            {1,2,3},
            {4,5,6},
            {7,8,9}}; //This is your original array

    int temp = 0; //declare a temp variable that will hold a swapped value

    for (int i = 0; i < array[0].length; i++){
        for (int j = 0; j < array[i].length; j++){
            if (i < array.length - 1 && j == array[i].length - 1){ //Make sure swapping only
                temp = array[i][j];                                //occurs within the boundary  
                array[i][j] = array[i+1][0];                       //of the array. In this case
                array[i+1][0] = temp;                              //we will only swap if we are
            }                                                      //at the last element in each
        }                                                          //row (j==array[i].length-1)
    }                                                              //3 elements, but index starts
                                                                   //at 0, so last index is 2 
  }                                                                   
  }