2014-11-29 3 views
1

Я пишу программу, которая определяет, есть ли четыре последовательных равных целых числа в двумерном массиве, в котором пользователь вводит размеры. Я что часть здесь написано:Как реализовать линейное сканирование на двумерном массиве?

public class FourConsecutiveNumbers { 

public static void main(String[] args) { 

    Scanner rowDimension = new Scanner(System.in); 
    System.out.print("Enter the number of rows: "); 
    int firstInput = rowDimension.nextInt(); 

    Scanner columnDimension = new Scanner(System.in); 
    System.out.print("Enter the number of columns: "); 
    int secondInput = columnDimension.nextInt(); 

    int[][] randomTable = new int[firstInput][secondInput]; 
    for (int row = 0; row < firstInput; row++) { 
     for (int column = 0; column < secondInput; column++) { 
      randomTable[row][column] = (int)(Math.random() * 10 + 0); 
      System.out.print(randomTable[row][column] + " "); 
     } 
     System.out.println(); 
    } 
} 
} 

Так, например, если пользователь вводит размеры как 5x4, это то, что массив будет выглядеть, если там были четыре последовательных равных целых чисел в нем ...

2 5 8 7 1 
3 2 9 4 7 
5 1 2 0 3 
8 0 1 2 7 

В этой таблице два появляются последовательно, по диагонали от первого места. Это также может быть так:

9 5 3 7 0 
2 5 7 3 1 
8 5 0 2 9 
4 5 1 7 5 

В этой таблице пять отображаются вертикально вниз со второго места.

Что я хочу сделать, это реализовать линейное сканирование по первой строке, чтобы определить, есть ли какие-либо последовательные равные целые числа, а затем сделать еще один столбцы, чтобы определить, есть ли последовательные равные целые числа. Кто-нибудь знает, как я это сделаю? Я думаю, если это будет диагонально, я бы вернул его, если есть совпадение выше или ниже слева или справа 1 пятно, и это происходит четыре раза. Но я не знаю, как сделать линейное сканирование, которое действительно понравится кому-то.

+0

Не будет ли это просто 'for' loop? – zapl

ответ

0

Я не знаю, насколько уместен этот вопрос, но я отправлю свой ответ и другим. Следующий метод выполняет итерацию через весь 2D-массив в одном for -loop.

Когда речь идет о двумерном массиве, элемент может иметь только четыре последовательных числа, если пространства достаточно, горизонтально и/или вертикально. Поэтому я добавил два других метода: isCandidateForward и isCandidateBackward, которые будут проверять, если данный элемент имеет достаточно места спереди/снизу или позади него.

См матрицу

1 1 2 3 3 
4 4 9 9 9 
4 4 9 9 9 
4 4 9 9 9 

Здесь элементы с номером 1 являются кандидатом для «горизонтального», «вертикального» и «по диагонали вперед» (вверх слева вниз направо) чеки, потому что есть достаточное количество элементов спереди/ниже них.
2 является единственным кандидатом на «вертикальную» проверку.
3 является кандидатом на проверку «по вертикали» и «по диагонали назад» (вверх-налево-вниз).
4 является только кандидатом на «горизонтальную» проверку.
Элементы 9 не могут быть отправной точкой для «последовательной группы номеров», так как для них недостаточно места спереди/сзади/позади них.

Ниже приведен код, который делает именно это. Он должен охватывать все возможные случаи.

/** 
* Checks, if a matrix contains four consecutive equal integers. These can appear horizontally, 
* vertically and diagonally. The matrix is assumed to be of consistent dimensions MxN. 
* This method performs a linear scan. 
* The matrix will be iterated in the following way: 
* E.g.: 0 1 2 3 4 
*  0 [0 ,1 ,2 ,3 ,4 ] 
*  1 [5 ,6 ,7 ,8 ,9 ] 
*  2 [10,11,12,13,14] 
*  3 [15,16,17,18,19] 
* The outside numbers denote rowIndex (vertical) and colIndex (horizontal). 
* The inside numbers denote the loop index. 
* 
* @param randomTable the matrix to check 
* @return if the matrix contains four consecutive integers. 
*/ 
public static boolean hasFourConsecutiveIntegers(int[][] randomTable) { 
    //Rule out matrices with rows < 4 and columns < 4 
    if (randomTable.length < 4 && randomTable[0].length < 4) { 
     return false; 
    } 

    int rows = randomTable.length; 
    int cols = randomTable[0].length; 
    int elementCount = rows * cols; 

    //linear scan; iterates row by row 
    for (int index = 0; index < elementCount; index++) { 
     int rowIndex = index/cols; 
     int colIndex = index % cols; 
     int currElement = randomTable[rowIndex][colIndex]; 

     //The following checks are for preventing IndexOutOfBoundsExceptions in the upcoming code. 
     //candidate for horizontal check 
     boolean horizontalCandidate = isCandidateForward(cols, colIndex); 
     //candidate for vertical check 
     boolean verticalCandidate = isCandidateForward(rows, rowIndex); 
     //candidate for diagonal up-left to down-right check 
     boolean diagonalForward = horizontalCandidate && verticalCandidate; 
     //candidate for diagonal up-right to down-left check 
     //needs different treatment because of backwards direction 
     boolean diagonalBackward = isCandidateBackward(colIndex) && verticalCandidate; 

     if (horizontalCandidate) { 
      boolean horizontalConsecutive = randomTable[rowIndex][colIndex + 1] == currElement && 
              randomTable[rowIndex][colIndex + 2] == currElement && 
              randomTable[rowIndex][colIndex + 3] == currElement; 
      if(horizontalConsecutive) { 
       return true; 
      } 
     } 
     if (verticalCandidate) { 
      boolean verticalConsecutive = randomTable[rowIndex + 1][colIndex] == currElement && 
              randomTable[rowIndex + 2][colIndex] == currElement && 
              randomTable[rowIndex + 3][colIndex] == currElement; 
      if(verticalConsecutive) { 
       return true; 
      } 
     } 
     if (diagonalForward) { 
      boolean diagonalFConsecutive = randomTable[rowIndex + 1][colIndex + 1] == currElement && 
              randomTable[rowIndex + 2][colIndex + 2] == currElement && 
              randomTable[rowIndex + 3][colIndex + 3] == currElement; 
      if(diagonalFConsecutive) { 
       return true; 
      } 
     } 
     if (diagonalBackward) { 
      boolean diagonalBConsecutive = randomTable[rowIndex + 1][colIndex - 1] == currElement && 
              randomTable[rowIndex + 2][colIndex - 2] == currElement && 
              randomTable[rowIndex + 3][colIndex - 3] == currElement; 
      if(diagonalBConsecutive) { 
       return true; 
      } 
     } 
    } 

    return false; 
} 

Методы хелперы isCandidateForward и isCandidateBackward:

/** 
* Checks, if at least four elements can fit consecutively after a 
* specific index (inclusive) of a dimension (rows/columns). 
* E.g.: 0 1 2 3 4 
*  0 [0 ,1 ,2 ,3 ,4 ] 
*  1 [5 ,6 ,7 ,8 ,9 ] 
*  2 [10,11,12,13,14] 
*  3 [15,16,17,18,19] 
*  
* If you choose rows and rowIndex = 0, isCandidateForward(rows, rowIndex) would return true. 
* Because starting from row 0, there are at least 4 consecutive elements vertically (0,5,10,15). 
* The same is true for (1,6,11,16), (2,7,12,17), (3,8,13,18) and (4,9,14,19). 
* 
* @param dimension the amount of rows or columns in the matrix. 
* @param dimensionIndex the index of that specific row or column. 
* @return if at least four elements can fit consecutively starting at that index. 
*/ 
private static boolean isCandidateForward(int dimension, int dimensionIndex) { 
    return dimension - dimensionIndex >= 4; 
} 

/** 
* Checks, if at least four elements can fit consecutively before a 
* specific index (inclusive). 
* E.g.: [0,1,2,3,4] => indices 3 and 4 would return true, 
* because you can fit four consecutive elements before them (inclusive). 
* 
* @param dimension the amount of rows or columns in the matrix. 
* @param dimensionIndex the index of that specific row or column. 
* @return if at least four elements can fit consecutively starting at that index. 
*/ 
private static boolean isCandidateBackward(int dimensionIndex) { 
    return dimensionIndex >= 3; 
} 

Конечно, если вы хотите, чтобы проверить на более или менее 4 последовательных чисел, вам придется изменить методы, и переключить жестко закодированные числа для переменных. Кроме того, если вы хотите получить больше информации, например, о том, где начинаются последовательные номера или сколько групп последовательных номеров, вам также нужно скорректировать код.

Следующий код демонстрирует результаты различных матриц. Просто вызовите метод test() где-нибудь в вашем коде.

private static void test() { 
    int[][] somewhereHorizontal1 = { { 1, 1, 1, 1, 2 }, 
            { 3, 4, 5, 6, 7 }, 
            { 7, 1, 8, 5, 4 }, 
            { 9, 9, 2, 5, 5 } }; 

    int[][] somewhereHorizontal2 = { { 3, 4, 5, 6, 7 }, 
            { 7, 1, 8, 5, 4 }, 
            { 1, 1, 1, 1, 2 }, 
            { 9, 9, 2, 5, 5 } }; 

    int[][] somewhereVertical1 = { { 3, 4, 5, 6, 7 }, 
            { 3, 1, 8, 5, 4 }, 
            { 3, 1, 4, 1, 2 }, 
            { 3, 9, 2, 5, 5 } }; 

    int[][] somewhereVertical2 = { { 3, 4, 5, 6, 7 }, 
            { 7, 2, 5, 5, 4 }, 
            { 1, 1, 5, 1, 2 }, 
            { 9, 9, 5, 7, 5 } }; 

    int[][] somewhereDiagonalF1 = { { 3, 4, 5, 6, 7 }, 
            { 7, 3, 8, 5, 4 }, 
            { 6, 1, 3, 1, 2 }, 
            { 9, 9, 2, 3, 5 } }; 

    int[][] somewhereDiagonalF2 = { { 3, 4, 5, 6, 7 }, 
            { 7, 1, 4, 5, 4 }, 
            { 1, 2, 1, 4, 2 }, 
            { 9, 9, 2, 5, 4 } }; 

    int[][] somewhereDiagonalB1 = { { 3, 4, 5, 6, 7 }, 
            { 7, 1, 6, 5, 4 }, 
            { 7, 6, 1, 1, 2 }, 
            { 6, 9, 2, 5, 5 } }; 

    int[][] somewhereDiagonalB2 = { { 3, 4, 5, 6, 7 }, 
            { 7, 1, 8, 7, 4 }, 
            { 1, 4, 7, 1, 2 }, 
            { 9, 7, 2, 5, 5 } }; 

    int[][] nowhere = { { 3, 4, 5, 6, 7 }, 
         { 7, 1, 8, 5, 4 }, 
         { 1, 4, 7, 1, 2 }, 
         { 9, 3, 2, 5, 5 } }; 

    //2nd row 6th element: DiagonalB: 9 
    int[][] somewhereBigTable = {{1,6,8,4,3,6,2}, 
           {8,3,6,1,5,9,3}, 
           {4,4,6,2,9,8,1}, 
           {7,7,1,9,1,4,9}, 
           {5,2,9,1,1,9,2}, 
           {5,5,6,2,3,3,8}, 
           {8,3,3,5,2,7,7}}; 

    int[][] nowhereBigTable = {{1,6,8,4,3,6,2}, 
           {8,3,6,1,5,9,3}, 
           {4,4,6,2,3,8,1}, 
           {7,7,1,9,1,4,9}, 
           {5,2,9,1,1,9,2}, 
           {5,5,6,2,3,3,8}, 
           {8,3,3,5,2,7,7}}; 

    printResults("somewhereHorizontal1", somewhereHorizontal1); 
    printResults("somewhereHorizontal2", somewhereHorizontal2); 
    printResults("somewhereVertical1", somewhereVertical1); 
    printResults("somewhereVertical2", somewhereVertical2); 
    printResults("somewhereDiagonalF1", somewhereDiagonalF1); 
    printResults("somewhereDiagonalF2", somewhereDiagonalF2); 
    printResults("somewhereDiagonalB1", somewhereDiagonalB1); 
    printResults("somewhereDiagonalB2", somewhereDiagonalB2); 
    printResults("nowhere", nowhere); 
    printResults("somewhereBigTable", somewhereBigTable); 
    printResults("nowhereBigTable", nowhereBigTable); 
} 

private static void printResults(String message, int[][] table) { 
    System.out.println(message); 
    for (int row = 0; row < table.length; row++) { 
     for (int column = 0; column < table[row].length; column++) { 
      System.out.print(table[row][column] + " "); 
     } 
     System.out.println(); 
    } 
    System.out.println("Consecutive? ==> " + hasFourConsecutiveIntegers(table)); 
    System.out.println("------------------------------------"); 
} 
Смежные вопросы