Найти элементы, окружающие элемент в массиве



У меня есть многомерный массив, я хочу получить элементы, окружающие конкретный элемент в этом массиве.



Например, если у меня есть следующее:



[[1,2,3,4,5,6]
[8,9,7,5,2,6]
[1,6,8,7,5,8]
[2,7,9,5,4,3]
[9,6,7,5,2,1]
[4,7,5,2,1,3]]


Как мне найти все 8 элементов вокруг любого из вышеперечисленных элементов? И как мне позаботиться о элементах по краям?



Один из способов, который я понял, - это написать 9-строчный код для этого, что очевидно, но есть ли лучшее решение?

652   8  

8 ответов:

Вы можете использовать "массив направлений" в форме

[[-1,-1], [-1,0],[1,0]..and so on]

И метод, который берет координату точки и перебирает массив направлений - > добавляет номера направлений к координатам, проверяет индексы не выходят за пределы и собирает результаты. Что-то вроде этого:

private static int[][] directions = new int[][]{{-1,-1}, {-1,0}, {-1,1},  {0,1}, {1,1},  {1,0},  {1,-1},  {0, -1}};

static List<Integer> getSurroundings(int[][] matrix, int x, int y){
    List<Integer> res = new ArrayList<Integer>();
    for (int[] direction : directions) {
        int cx = x + direction[0];
        int cy = y + direction[1];
        if(cy >=0 && cy < matrix.length)
            if(cx >= 0 && cx < matrix[cy].length)
                res.add(matrix[cy][cx]);
    }
    return res;
}

Ибо (i, j) ->

              (i - 1, j - 1)
              (i - 1, j)
              (i - 1, j + 1)

              (i, j - 1)
              (i, j + 1)

              (i + 1, j - 1)
              (i + 1, j)
              (i + 1, j + 1)

Теперь, по краям, вы можете проверить наличие num % row == 0, затем его на краю строки... и, num % col == 0 затем его край столбца..

Вот как вы можете действовать: -

Задан индекс (i, j).. Вы можете найти элементы в строках, соседних с j для i - 1, затем i, а затем i + 1. (Примечание: - для индекса i вам просто нужно получить доступ к j - 1 и j + 1)

Впоследствии вы также можете проверить для row edge и column edge..

Здесь, вы можете посмотреть на код ниже, как это может произойти: -

    // Array size
    int row = 6;
    int col = 6;
    // Indices of concern
    int i = 4;
    int j = 5;

    // To the left of current Column
    int index = i - 1;
    for (int k = -1; k < 2; k++) {
        if (index % row > 0 && ((j + k)  % col) > 0) {
            System.out.println(arr[index][j + k]);
        }
    }


    // In the current Column
    index = i;

    // Increment is 2 as we don't want (i, j)
    for (int k = -1; k < 2; k = k + 2) {            
        if (index % row > 0 && ((j + k)  % col) > 0) {
            System.out.println(arr[index][j + k]);
        }
    }

    // To the right of current Column
    index = i + 1;
    for (int k = -1; k < 2; k++) {
        if (index % row > 0 && ((j + k)  % col) > 0) {
            System.out.println(arr[index][j + k]);
        }

    }

UPDATE : - приведенный выше код может быть дополнительно упрощен.. Но я оставляю эту задачу вам.. подсказка : - вы можете уменьшить один для цикла оттуда..

for (i = 0; i < array.length; i++) {
            for (j = 0; j < array[i].length; j++) {
                for (x = Math.max(0, i - 1); x <= Math.min(i + 1, array.length); x++) {
                    for (y = Math.max(0, j - 1); y <= Math.min(j + 1,
                            array[i].length); y++) {
                        if (x >= 0 && y >= 0 && x < array.length
                                && y < array[i].length) {
                            if(x!=i || y!=j){
                            System.out.print(array[x][y] + " ");
                            }
                        }
                    }
                }
                System.out.println("\n");
            }
        }

Спасибо всем людям, которые ответили, но я понял это с помощью этого поста, который я нашел только сейчас, и выше есть решение. еще раз спасибо:)

Базовый случай - это просто получение соседних элементов путем индексации сдвига. Ибо (i,j) это будет (i + 1, j), (i - 1, j), и т.д.

На ребрах я использую два подхода:

    Оператор
  1. по модулю % позволяет избежать исключения IndexOutOfBounds, но его иногда путают с неправильной индексацией элементов.
  2. оберните матрицу одним слоемэлементов по умолчанию . Он добавляет некоторое экстрапространство для хранения матриц, но делает ваш код более читаемым без перехвата исключений, lot ifs и так далее. Этот трюк часто используется при представлении лабиринта в виде матрицы.

Пример: ваш элемент по умолчанию равен 0.

0 0 0 0 0 0
0 1 2 3 4 0
0 2 6 7 3 0
0 1 3 5 7 0
0 2 4 6 2 0
0 0 0 0 0 0

Примечание: не забудьте перебрать фактический размер массива, а не расширенный.

Это мое решение для вашей проблемы, написанное на Ruby. вместо вычисления, если элемент находится на краю, вы можете обращаться к элементам "через" край и обрабатывать" нулевые " значения или исключения, которые там происходят. затем удалите значения " nil " из окончательного списка. Это решение не так хорошо, как вычисление, если какая-то "точка" находится за краем или нет.

big_map = [[1,2,3,4,5,6],
           [8,9,7,5,2,6],
           [1,6,8,7,5,8],
           [2,7,9,5,4,3],
           [9,6,7,5,2,1],
           [4,7,5,2,1,3]]

# monkey patch classes to return nil.
[NilClass, Array].each do |klass|
    klass.class_eval do
        def [](index)
            return nil if index < 0 or index > self.size rescue nil
            self.fetch(index) rescue nil
        end
    end
end

class Array

    # calculate near values and remove nils with #compact method.   
    def near(i,j)
        [ self[i - 1][j - 1], self[i - 1][j - 0], self[i - 1][j + 1],
          self[i - 0][j - 1],                     self[i - 0][j + 1],
          self[i + 1][j - 1], self[i + 1][j - 0], self[i + 1][j + 1],
        ].compact
    end
end

puts big_map.near(1,1).inspect
# => [1, 2, 3, 8, 7, 1, 6, 8]

puts big_map.near(0,0).inspect
# => [2, 8, 9]

puts big_map.near(5,5).inspect
# => [2, 1, 1]

Я работал над той же проблемой и придумал небольшое оптимизированное решение, чтобы найти окружающие числа любой точки в 2D-матрице, надеюсь, это поможет, пожалуйста, прокомментируйте, если я могу сократить логику как-то Код: -

import java.util.ArrayList;

public class test {
    public static void main(String[] arg){

        int[][] arr = {{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}};
        //int[][] arr = {{width,2,3},{4,5,6},{7,8,9}};
        ArrayList<Integer> al = new ArrayList<Integer>();
        int x = 2, y = 2;
        int width = 2; //change the value of width, according to the requirement 
        for(int i = 0; i < 5; i++){
            for(int j = 0; j < 5; j++){
                if( (i == (x-width) && ( (y+width) >= j && j >= (y-width))) || (i == (x+width) && ( (y+width) >= j && j >= (y-width))) || (j == (y-width) && ( (x+width) >= i && i >= (x-width))) || (j == (y+width) && ( (x+width) >= i && i >= (x-width)))  ){
                    //if( x >= 0 && i < (i+width) && y >= 0 && j < (j+width))
                        {
                        al.add(arr[i][j]);
                        }
                }
            }
        }
        System.out.println(al);
    }

}

Вы не упомянули, хотите ли вы циклические соседи для ребер или игнорируете циклические соседи. Предполагая, что вам нужны циклические соседи, вот код,

List<Integer> getNeighbours(int[][] mat, int x, int y){
  List<Integer> ret = new ArrayList<Integer>();
  int rows = mat.length;
  int cols = mat[0].length;
  for(int i=-1,i<=1;i++)
    for(int j=-1;j<=1;j++)
      if(i||j) ret = ret.add(mat[(x+i)%rows][(y+j)%cols]);
  return ret;
}
(x-1, y-1) -> upper left
(x-1, y) -> left
(x-1, y+1) -> lower left

(x, y+1) -> up
(x, y) -> current position
(x, y-1) -> down

(x+1, y+1) -> upper right
(x+1, y) -> right
(x+1, y-1) -> lower right

Вы можете использовать это как руководство. Теперь все, что вам нужно сделать, это добавить их в try catch.

 for( int x=0; x<arr.length; x++ ){
  for(int y=0; y<arr[x].length; y++){
  if( arr[x][y] == 8 ){
    try{
      System.out.println("Upper Left is: " + arr[x-1][y-1]);
    }catch(ArrayIndexOutOfBoundsException e){
     //do something
    }


    try{
      System.out.println("Left is: " + arr[x-1][y]);
    }catch(ArrayIndexOutOfBoundsException e){
     //do something
    }

    //.....and others
   }
  }

Comments

    Ничего не найдено.