Как обработать список из списка Integer и найти соседей? - PullRequest
1 голос
/ 23 декабря 2019

В настоящее время я пытаюсь решить проблему, в которой входные данные должны быть следующими:

int hours(int rows, int columns, List<List<Integer> > grid)

Где сетка списка представляет собой матрицу из 0 и 1 (0 означает, что она не завершена, 1 означает, что она завершена) следующим образом:

0 1 1 0 1 
0 1 0 1 0 
0 0 0 0 1 
0 1 0 0 0 

Каждое значение представляет машину в сети, отправляющую файлы друг другу, поэтому, если значение равно «1», этот узел может отправлять файлы на ALL NEIGHBORS (Диагональные не учитываются только вверх / вниз / вправо / влево). Проблема в том, что как только 0 становится 1 (зависит от соседней ячейки), он не может отправить файл любому другому соседу до 1 ЧАСА.

Цель проблемы - вернуть сколько часов потребуется, чтобы все узлы получили файлы? (другими словами, вся Матрица становится равной 1. Учитывая сложность времени выполнения

Для наглядного объяснения: (После первого часа это должно быть состояние матрицы, которое рассматривается как итерация):

 1 1 1 1 1
 1 1 1 1 1
 0 1 0 1 1
 1 1 1 0 1

Итак, я следовал подходу, при котором я перебираю матрицу, просматривая предоставленную сетку и добавляя значения во временный массив (поскольку я не знаю, как обновить или добавить значения списка внутриосновной список). Затем, когда индекс строки достиг максимума, я добавляю 1 час к переменной int и добавляю значения в основную сетку.

Я знаю, что приведенный ниже код еще не работает / завершается и может иметьсинтаксические ошибки, но вы понимаете идею и подход.

Мой вопрос: есть ли более простой и эффективный метод, чем мой? Я также нашел решение здесь Но это работает только с 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 ;
}

Ответы [ 2 ]

1 голос
/ 23 декабря 2019

Если вам разрешено обновлять grid, используйте grid.get(y).get(x) для проверки сетки и grid.get(y).set(x, value) для обновления сетки. Если вам не разрешено обновлять сетку, начните с копирования значений в int[][] 2D-массив, затем используйте это вместо этого в приведенном ниже решении.

Сканируйте сетку на наличие 0 значений и добавьтекоординаты Queue<Point>, например ArrayDeque<Point>, где Point - это объект с двумя int полями, например, java.awt.Point класс.

Мы делаем эточтобы обеспечить хорошую производительность, при сложности выполнения, например, O (нм) , где n и m - ширина и высота сетки.

Запустите цикл с i = 1. В цикле итерируйте очередь. Если точка имеет соседнее значение, равное i, установите значение точки на i + 1, в противном случае добавьте точку во вторую очередь. В конце замените первую очередь на вторую, увеличьте i на 1 и делайте это снова, пока очередь не станет пустой.

В результате получается последовательность 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, так как это имеет больше смысла.

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

Для тестирования, построения List<List<Integer>> и отправкив отдельных rows и columns значениях громоздко, поэтому вот вспомогательный метод:

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 },
}));

Вывод

2
3
0 голосов
/ 23 декабря 2019

Это, похоже, работает.


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


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...