Java 如何处理列表整数列表并查找邻居?

Java 如何处理列表整数列表并查找邻居?,java,algorithm,data-structures,runtime,time-complexity,Java,Algorithm,Data Structures,Runtime,Time Complexity,我目前正在尝试解决一个问题,输入应该如下 int hours(int rows, int columns, List<List<Integer> > grid) 每个值表示网络中一台相互发送文件的机器,因此如果该值为“1”,则该节点能够将文件发送到所有邻居(对角值不仅计算向上/向下/向右/向左)。问题是一旦0变为1(受邻居单元影响)它无法在1小时前将文件发送给任何其他邻居 问题的目标是返回在所有节点接收文件之前需要多少小时?(换句话说,考虑到运行时复杂性,所有矩阵变为1

我目前正在尝试解决一个问题,输入应该如下

int hours(int rows, int columns, List<List<Integer> > grid)
每个值表示网络中一台相互发送文件的机器,因此如果该值为“1”,则该节点能够将文件发送到所有邻居(对角值不仅计算向上/向下/向右/向左)。问题是一旦0变为1(受邻居单元影响)它无法在1小时前将文件发送给任何其他邻居

问题的目标是返回在所有节点接收文件之前需要多少小时?(换句话说,考虑到运行时复杂性,所有矩阵变为1。

视觉解释:(在第一个小时后,这应该是被视为迭代的矩阵状态):

因此,我采用了一种方法,在提供的网格中遍历矩阵并在临时数组中追加值(因为我不知道如何更新或追加主列表中的列表值)。然后,一旦行索引达到最大值,我向int变量添加1小时,并向主网格添加值

我知道下面的代码还没有运行/完成,可能有语法错误,但你明白了想法和方法

我的问题是,有没有比我更简单、更有效的方法?我也找到了一个解决方案,但如果我的想法值得的话,它只适用于2D数组。然而,这4个嵌套循环不会破坏代码的复杂性吗

    List<List<Integer>> grid2 = grid1;
    boolean received= false;
    int hours=0;
    int rows_Temp = 0 ;
    int columsTemp = 0 ;
    int[][] grid2 = null ;
    while(rows_Temp<rows&&!received)
    {
        if(rows_Temp==rows-1)
        { 
            rows_Temp=0;
        }
        if(rows_Temp==0) 
        {
            //create an array with the grid dimention
            grid2= new int[rows][columns];
        }
        //manage top left corner
        if(rows_Temp==0 && columsTemp == 0 ) 
        {
            //find right & down
            int center= grid.get(rows_Temp).get(columsTemp);
            int right = grid.get(rows_Temp).get(columsTemp+1);
            int down  = grid.get(rows_Temp+1).get(columsTemp);


            if(center==1)
            {
                if(right==0)
                {
                    grid2[rows_Temp][columsTemp+1] = 1;
                }
                if(down==0)
                {
                    grid2[rows_Temp+1][columsTemp]=1;
                }
            }
        }
        //manage top right corner
        else if(rows_Temp==0 && columsTemp == columns-1)
        {
            //find left and down
            int center= grid.get(rows_Temp).get(columsTemp);
            int left = grid.get(rows_Temp).get(columsTemp-1);
            int down  = grid.get(rows_Temp+1).get(columsTemp);

            if(center==1)
            {
                if(left==0)
                {
                    grid2[rows_Temp][columsTemp-1] = 1;
                }
                if(down==0)
                {
                    grid2[rows_Temp+1][columsTemp]=1;
                }
            }
        }
        //mange down left corner of the array
        else if(rows_Temp==rows-1 && columsTemp == 0)
        {
            //find up and right
            int center= grid.get(rows_Temp).get(columsTemp);
            int right = grid.get(rows_Temp).get(columsTemp+1);
            int up  = grid.get(rows_Temp-1).get(columsTemp);

            if(center==1)
            {
                if(right==0)
                {
                    grid2[rows_Temp][columsTemp+1] = 1;
                }
                if(up==0)
                {
                    grid2[rows_Temp-1][columsTemp]=1;
                }
            }
        }
        //manage down right corner
        else if(rows_Temp==rows-1 && columsTemp == columns-1)
        {
            //find left and up
            int center= grid.get(rows_Temp).get(columsTemp);
            int left = grid.get(rows_Temp).get(columsTemp-1);
            int up  = grid.get(rows_Temp-1).get(columsTemp);

            if(center==1)
            {
                if(left==0)
                {
                    grid2[rows_Temp][columsTemp-1] = 1;
                }
                if(up==0)
                {
                    grid2[rows_Temp-1][columsTemp]=1;
                }
            }
        }
        //manage left sides but not corners
        else if(rows_Temp!=0&& rows_Temp!=rows-1&& columsTemp==0)
        {
            int center= grid.get(rows_Temp).get(columsTemp);
            int right = grid.get(rows_Temp).get(columsTemp+1);
            int up  = grid.get(rows_Temp-1).get(columsTemp);
            int down  = grid.get(rows_Temp+1).get(columsTemp);

            if(center==1)
            {
                if(right==0)
                {
                    grid2[rows_Temp][columsTemp+1] = 1;
                }
                if(up==0)
                {
                    grid2[rows_Temp-1][columsTemp]=1;
                }
                if(down==0)
                {
                    grid2[rows_Temp+1][columsTemp]=1;
                }
            }  
        }    

        if(columsTemp==columns-1)
        {
            columsTemp=0;
            rows_Temp++;
            System.out.println();
        }
        else
        {
            columsTemp++;
        }


    }
    System.out.println("------------");
    return 0 ;
}
List grid2=grid1;
布尔值=假;
整小时=0;
int rows_Temp=0;
int columnstemp=0;
int[][]grid2=null;

while(rows_Temp如果允许更新
grid
,请使用
grid.get(y).get(x)
检查网格,并使用
grid.get(y).set(x,value)
更新网格。如果不允许更新网格,请先将值复制到
int[][]
2D数组中,然后在下面的解决方案中使用该数组

扫描网格中的
0
值,并将坐标添加到
队列中,例如
ArrayDeque
,其中
点是一个具有两个
int
字段的对象,例如类

我们这样做是为了确保良好的性能,运行时复杂性为O(nm),其中
n
m
是网格的宽度和高度

i=1
开始一个循环。在循环中,迭代队列。如果该点的相邻值等于
i
,则将该点的值设置为
i+1
,否则将该点添加到第二个队列中。最后,将第一个队列替换为第二个队列,将
i
增加1,然后再次执行该操作,直到队列处于emp状态泰

结果是2D矩阵的级数如下所示:

0 1 1 0 1   →   2 1 1 2 1   →   2 1 1 2 1   →   2 1 1 2 1
0 1 0 0 0   →   2 1 2 0 2   →   2 1 2 3 2   →   2 1 2 3 2
0 0 0 0 1   →   0 2 0 2 1   →   3 2 3 2 1   →   3 2 3 2 1
0 0 0 1 0   →   0 0 2 1 2   →   0 3 2 1 2   →   4 3 2 1 2
矩阵中的最高值为4,因此答案为3小时,比最高值少1小时


更新

下面是代码,它将输入复制到二维数组,并将值降低1,因为这样更有意义

static int hours(int rows, int columns, List<List<Integer>> grid) {
    // Build hourGrid, where value is the number of hours until the
    // node can send, with MAX_VALUE meaning the node cannot send.
    // Also build queue of nodes that cannot send.
    int[][] hourGrid = new int[rows][columns];
    Queue<Point> pending = new ArrayDeque<>();
    for (int y = 0; y < rows; y++) {
        for (int x = 0; x < columns; x++) {
            if (grid.get(y).get(x) == 0) {
                hourGrid[y][x] = Integer.MAX_VALUE;
                pending.add(new Point(x, y));
            }
        }
    }

    // Keep iterating the queue until all pending nodes can send.
    // Each iteration adds 1 hour to the total time.
    int hours = 0;
    for (; ! pending.isEmpty(); hours++) {
        // Check all pending nodes if they can receive data
        Queue<Point> notYet = new ArrayDeque<>();
        for (Point p : pending) {
            if ((p.x > 0           && hourGrid[p.y][p.x - 1] <= hours)
             || (p.x < columns - 1 && hourGrid[p.y][p.x + 1] <= hours)
             || (p.y > 0           && hourGrid[p.y - 1][p.x] <= hours)
             || (p.y < rows - 1    && hourGrid[p.y + 1][p.x] <= hours)) {
                // Node can receive from a neighbor, so will be able to send in 1 hour
                hourGrid[p.y][p.x] = hours + 1;
            } else {
                // Not receiving yet, so add to queue for next round
                notYet.add(p);
            }
        }
        pending = notYet;
    }
    return hours;
}
试验

输出

2
3.
这似乎奏效了


      List<List<Integer>> grid = 
            new ArrayList<>(List.of(
      new ArrayList<>(List.of(0, 1, 1, 0, 1)),
      new ArrayList<>(List.of( 0, 1, 0, 1, 0)),
      new ArrayList<>(List.of( 0, 0, 0, 0, 1)),
      new ArrayList<>(List.of( 0, 1, 0, 0, 0))));

      int total =0; 
      while (hours(4,4,grid) > 0) {
         total++;
      }

      System.out.println(total + " hours");

   }

   public static void display(List<List<?>> grid) {
      for (List<?> row : grid) {
         System.out.println(row);
      }
      System.out.println();
   }
   public static int hours(int rows, int cols, List<List<Integer>> grid) {
      int count = 0;

      // count the remaining 0's and change
      // the new guys to 1.
      for (int r = 0; r < rows; r++) {
         for (int c = 0; c < cols; c++) {
            if (grid.get(r).get(c) == 0) {
               count++;
            }
            if (grid.get(r).get(c) == -2) {
               grid.get(r).set(c, 1);
            }
         }
      }
      if (count == 0) {
         return 0;
      }
      for (int r = 0; r < rows; r++) {
         for (int c = 0; c < cols; c++) {

            if (grid.get(r).get(c) == 1 && grid.get(r).get(c) != -2) {
               if (r + 1 < rows) {
                  if (grid.get(r + 1).get(c) == 0) {
                     grid.get(r + 1).set(c, -2);
                  }
               }
               if (r - 1 >= 0) {
                  if (grid.get(r - 1).get(c) == 0) {
                     grid.get(r - 1).set(c, -2);
                  }
               }
               if (c + 1 < cols) {
                  if (grid.get(r).get(c + 1) == 0) {
                     grid.get(r).set(c + 1, -2);
                  }
               }
               if (c - 1 >= 0) {
                  if (grid.get(r).get(c - 1) == 0) {
                     grid.get(r).set(c - 1, -2);
                  }
               }
            }
         }
      }

      return count;
   }
}



列表网格=
新建ArrayList(列表中的(
新的ArrayList(列表(0,1,1,0,1)),
新的ArrayList(列表(0,1,0,1,0)),
新的ArrayList(列表(0,0,0,0,1)),
新的数组列表(0,1,0,0,0的列表);
int-total=0;
而(小时数(4,4,网格)>0){
总计++;
}
系统输出打印项次(总+小时);
}
公共静态无效显示(列表行:网格){
系统输出打印项次(行);
}
System.out.println();
}
公共静态整数小时(整数行、整数列、列表网格){
整数计数=0;
//计算剩余的0并进行更改
//新来的家伙们到1号。
对于(int r=0;r=0){
if(grid.get(r-1).get(c)==0){
grid.get(r-1).set(c,-2);
}
}
if(c+1=0){
if(grid.get(r).get(c-1)==0){
grid.get(r.set)(c-1,-2);
}
}
}
}
}
返回计数;
}
}

根据您的示例,我假设对角邻域不计算在内。是的,仅向上/向下/向右/向左您应该从最初的1开始进行广度优先搜索。遍历所有单元格所需的层数是填充矩阵所需的小时数。好的,谢谢,我将搜索算法,但在此之前将检查surrounding top/down/left-right,并且能够将0改为1??不确定我是否已经告诉了您所述的问题……但是我在问题中写的第二次迭代发生在第一个小时的末尾……典型测试用例的解决方案将是2小时,因为第三次迭代将把所有的问题都变成一个。我完全理解这一点fo grid.get(y).set(x,value)我正在搜索它。我的解决方案中唯一的问题是,在整个迭代结束之前,您将无法编辑主网格。换句话说,当一个具有1的节点更改邻居时,它只会影响它们
static int hours(int rows, int columns, List<List<Integer>> grid) {
    // Build hourGrid, where value is the number of hours until the
    // node can send, with MAX_VALUE meaning the node cannot send.
    // Also build queue of nodes that cannot send.
    int[][] hourGrid = new int[rows][columns];
    Queue<Point> pending = new ArrayDeque<>();
    for (int y = 0; y < rows; y++) {
        for (int x = 0; x < columns; x++) {
            if (grid.get(y).get(x) == 0) {
                hourGrid[y][x] = Integer.MAX_VALUE;
                pending.add(new Point(x, y));
            }
        }
    }

    // Keep iterating the queue until all pending nodes can send.
    // Each iteration adds 1 hour to the total time.
    int hours = 0;
    for (; ! pending.isEmpty(); hours++) {
        // Check all pending nodes if they can receive data
        Queue<Point> notYet = new ArrayDeque<>();
        for (Point p : pending) {
            if ((p.x > 0           && hourGrid[p.y][p.x - 1] <= hours)
             || (p.x < columns - 1 && hourGrid[p.y][p.x + 1] <= hours)
             || (p.y > 0           && hourGrid[p.y - 1][p.x] <= hours)
             || (p.y < rows - 1    && hourGrid[p.y + 1][p.x] <= hours)) {
                // Node can receive from a neighbor, so will be able to send in 1 hour
                hourGrid[p.y][p.x] = hours + 1;
            } else {
                // Not receiving yet, so add to queue for next round
                notYet.add(p);
            }
        }
        pending = notYet;
    }
    return hours;
}
static int hours(int[][] grid) {
    final int rows = grid.length;
    final int columns = grid[0].length;
    List<List<Integer>> gridList = new ArrayList<>(rows);
    for (int[] row : grid) {
        List<Integer> rowList = new ArrayList<>(columns);
        for (int value : row)
            rowList.add(value); // autoboxes
        gridList.add(rowList);
    }
    return hours(rows, columns, gridList);
}
System.out.println(hours(new int[][] { // data from question
    { 0, 1, 1, 0, 1 },
    { 0, 1, 0, 1, 0 },
    { 0, 0, 0, 0, 1 },
    { 0, 1, 0, 0, 0 },
}));
System.out.println(hours(new int[][] { // data from answer
    { 0, 1, 1, 0, 1 },
    { 0, 1, 0, 0, 0 },
    { 0, 0, 0, 0, 1 },
    { 0, 0, 0, 1, 0 },
}));

      List<List<Integer>> grid = 
            new ArrayList<>(List.of(
      new ArrayList<>(List.of(0, 1, 1, 0, 1)),
      new ArrayList<>(List.of( 0, 1, 0, 1, 0)),
      new ArrayList<>(List.of( 0, 0, 0, 0, 1)),
      new ArrayList<>(List.of( 0, 1, 0, 0, 0))));

      int total =0; 
      while (hours(4,4,grid) > 0) {
         total++;
      }

      System.out.println(total + " hours");

   }

   public static void display(List<List<?>> grid) {
      for (List<?> row : grid) {
         System.out.println(row);
      }
      System.out.println();
   }
   public static int hours(int rows, int cols, List<List<Integer>> grid) {
      int count = 0;

      // count the remaining 0's and change
      // the new guys to 1.
      for (int r = 0; r < rows; r++) {
         for (int c = 0; c < cols; c++) {
            if (grid.get(r).get(c) == 0) {
               count++;
            }
            if (grid.get(r).get(c) == -2) {
               grid.get(r).set(c, 1);
            }
         }
      }
      if (count == 0) {
         return 0;
      }
      for (int r = 0; r < rows; r++) {
         for (int c = 0; c < cols; c++) {

            if (grid.get(r).get(c) == 1 && grid.get(r).get(c) != -2) {
               if (r + 1 < rows) {
                  if (grid.get(r + 1).get(c) == 0) {
                     grid.get(r + 1).set(c, -2);
                  }
               }
               if (r - 1 >= 0) {
                  if (grid.get(r - 1).get(c) == 0) {
                     grid.get(r - 1).set(c, -2);
                  }
               }
               if (c + 1 < cols) {
                  if (grid.get(r).get(c + 1) == 0) {
                     grid.get(r).set(c + 1, -2);
                  }
               }
               if (c - 1 >= 0) {
                  if (grid.get(r).get(c - 1) == 0) {
                     grid.get(r).set(c - 1, -2);
                  }
               }
            }
         }
      }

      return count;
   }
}