2d阵列对角填充

时间:2014-09-18 20:37:52

标签: java arrays

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];
        }
    }
}

8 个答案:

答案 0 :(得分:9)

好吧,如果您要枚举索引以便填充该模式,那么您将获得

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

因此,您需要遍历两个索引的 total 。即,添加剂总量。如您所见,0,0总计0,1,00,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);
}

请注意,虽然此实现适用于所有矩阵大小(和形状),但它不会尽可能高效。其中nmatrix.length(假设为矩阵),此实现是大O表示法中的最佳O(n^2)类算法;但是,它有效地执行2*n^2次迭代,而最佳解决方案只执行n^2

答案 1 :(得分:7)

你希望得到这样的东西:

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

在大小为NxN的网格中,对于网格中的每个点(x,y),您可以像这样确定值(仍然需要对偏移量进行一些修正,参见最终公式):

  • 如果你在左上半部分,计算你上方和左边三角形的面积,并加上距离顶部的距离

  • 如果您位于右下角(或中间),请计算您下方和右侧三角形的面积,添加距离底部的距离并从整个区域中减去

让我们尝试一下公式:

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单位的机器,他们可以在一次操作中计算整个矩阵。

答案 2 :(得分:4)

M by N Matrix的对角线,具有稳健的数组格式

鉴于很多这些答案已经涵盖了基本的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));
}

打印二维数组

此方法专门用于此示例,方法是使用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's 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's 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}

答案 3 :(得分:2)

您需要从索引0..n转换为x / y(从0到x * y)并从索引转换回x / y ...

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

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

我已将实施细节留给您。

答案 4 :(得分:2)

卢克的直觉是一个很好的直觉 - 你通过左右对角线工作。需要注意的另一件事是对角线的长度: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));

答案 5 :(得分:2)

以下是从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;     
}

输入:

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

输出:

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

Click here for running test code

答案 6 :(得分:2)

这是一个简单的动态编程(ish)解决方案。你基本上可以从你最后的行动中学习。

注意: 这是O(N^2) ALGOIRTHM

<强> 初始化:

 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;
}

答案 7 :(得分:1)

以下是您的问题的完整工作代码。如果您愿意,可以复制并粘贴

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 
  }                                                                   
  }
相关问题