Найти элементы, окружающие элемент в массиве
У меня есть многомерный массив, я хочу получить элементы, окружающие определенный элемент в этом массиве.
Например, если у меня есть следующее:
[[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-строчный код для этого, что очевидно, но есть ли лучшее решение?
Ответы
Ответ 1
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");
}
}
Спасибо всем людям, которые ответили, но я понял это с помощью этого сообщения, которое я нашел сейчас, и выше - это решение. Еще раз спасибо:)
Ответ 2
Вы можете использовать "массив направлений" в форме
[[-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;
}
Ответ 3
Для (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]);
}
}
ОБНОВЛЕНИЕ: - Вышеупомянутый код может быть упрощен. Но я оставляю вам эту задачу.
СОВЕТ: - Вы можете уменьшить один из них для цикла.
Ответ 4
Базовый регистр - это просто получить соседние элементы путем смещения индексации. Для (i,j)
это будет (i + 1, j)
, (i - 1, j)
и т.д.
По краям я использую два подхода:
- Оператор Modulo
%
, чтобы избежать исключения IndexOutOfBounds
, но иногда он путается с индексацией неправильных элементов.
- Оберните свою матрицу одним слоем элементов по умолчанию. Он добавляет дополнительное пространство для хранения матриц, но делает ваш код более удобочитаемым, не вызывая исключения, много и так далее. Этот трюк часто используется при представлении лабиринта как матрицы.
Пример: ваш элемент по умолчанию - 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
Примечание. Не забывайте перебирать размер массива фактический, а не расширенный.
Ответ 5
Это мое решение для вашей проблемы, написанное на Ruby. Вместо того, чтобы вычислять, находится ли элемент у края, вы можете обращаться к элементам "поверх" края и обрабатывать значения "nil" или исключения, которые там происходят. Затем удалите значения "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]
Ответ 6
Я работал над одной и той же проблемой и придумал небольшое оптимизированное решение для поиска окружающих чисел любой точки в 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);
}
}
Ответ 7
Вы не упомянули, хотите ли вы циклических соседей для ребер или игнорируете циклических соседей. Предполагая, что вы хотите, чтобы циклические соседи здесь были кодом,
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;
}
Ответ 8
(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
}
}