【问题标题】:Find elements surrounding an element in an array查找数组中元素周围的元素
【发布时间】:2012-09-26 11:05:23
【问题描述】:

我有一个多维数组,我想获取该数组中特定元素周围的元素。

例如,如果我有以下情况:

[[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 行代码,这很明显,但是有更好的解决方案吗?

【问题讨论】:

  • 使用模数 (%) 处理边缘的情况...

标签: java arrays multidimensional-array


【解决方案1】:

您可以在表格中使用'方向数组'

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

【讨论】:

  • 嗨,很好的解决方案。是否可以将其扩展为,例如,围绕单个索引的一组内部周围元素获取周围元素?谢谢。
【解决方案2】:

对于 (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 - 1j + 1

随后您还可以检查row edgecolumn 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]);
        }

    }

更新 : - 上面的代码可以进一步简化.. 但我把这个任务留给你.. 提示:- 你可以从那里减少一个 for 循环..

【讨论】:

  • 似乎有一些1s 应该是ij(案例2 和案例7)。
  • @Rohit Jain:谢谢,我想通了,但是,我必须对多维数组的所有元素执行此操作,因此我需要找出遍历所有相邻元素的通用方法
  • @vineetrok 如果您将每个(i, j) 更改为(i % rows, j % cols),它将作为一般情况工作。
  • @Baz.. 不,那是我写的。最初我在第二种情况下写了1,但后来我用i替换了它。
  • @RohitJain 我不明白你对我的评论。对 vineetrok 的评论不正确。您不必事先检查它。您可以在访问权限内使用模数。见我之前的评论。
【解决方案3】:
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");
            }
        }

感谢所有回答的人,但我在刚刚找到的this post 的帮助下想通了,以上是解决方案。再次感谢:)

【讨论】:

    【解决方案4】:

    基本情况只是通过索引移位来获取相邻元素。对于(i,j),它将是(i + 1, j)(i - 1, j) 等。

    在边缘我使用两种方法:

    1. 取模% 运算符以避免IndexOutOfBounds 异常,但有时会与错误的元素索引混淆。
    2. 用一层默认元素包裹你的矩阵。它为保存矩阵添加了一些额外空间,但使您的代码更具可读性,而不会捕获异常、大量 if 等。这个技巧在将迷宫表示为矩阵时经常使用。

    示例:您的默认元素是 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
               }
              }
            

            【讨论】:

            • 你应该使用modulo (%)操作符进行边界检查。你不需要try-catch块来做这件事。
            • @gekkostate 如果你改变了例外,为什么不改变另一个呢?
            • @Baz 抱歉,我没有看到那个异常。
            猜你喜欢
            • 2016-08-08
            • 2021-01-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-30
            • 1970-01-01
            • 2019-12-06
            • 1970-01-01
            相关资源
            最近更新 更多