Диагональное заполнение массива 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];
}
}
}
Ответы
Ответ 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
}
}