1

https://judge.telerikacademy.com/problem/29largestareamatrix That's the exercise. Write a program that finds the largest area of equal neighbour elements in a rectangular matrix and prints its size. Input

On the first line you will receive the numbers N and M separated by a single space On the next N lines there will be M numbers separated with spaces - the elements of the matrix

Output

Print the size of the largest area of equal neighbour elements

Constraints

3 <= N, M <= 1024 Time limit: 0.5s for JAVA Memory limit: 50MB

And this is my solution.

import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static class Node {
        private int rowIndex, colIndex;

        Node(int rowIndex, int colIndex) {
            this.rowIndex = rowIndex;
            this.colIndex = colIndex;
        }

        Node[] getNeighbourNodes(int maxRowIndex, int maxColIndex) {
            Node[] nodes = new Node[4];

            int[][] indexesToCheck = {
                    {rowIndex - 1, colIndex},
                    {maxRowIndex - 1, colIndex},
                    {rowIndex + 1, colIndex},
                    {0, colIndex},
                    {rowIndex, colIndex - 1},
                    {rowIndex, maxColIndex - 1},
                    {rowIndex, colIndex + 1},
                    {rowIndex, 0}
            };

            for (int i = 0; i < indexesToCheck.length; i += 2) {
                int rowIndex = indexesToCheck[i][0], backupRowIndex = indexesToCheck[i + 1][0];
                int colIndex = indexesToCheck[i][1], backupColIndex = indexesToCheck[i + 1][1];
                if (indexExists(rowIndex, colIndex, maxRowIndex, maxColIndex)) {
                    nodes[i / 2] = new Node(rowIndex, colIndex);
                } else {
                    nodes[i / 2] = new Node(backupRowIndex, backupColIndex);
                }
            }

            return nodes;
        }

        private boolean indexExists(int row, int col, int maxRowIndex, int maxColIndex) {
            return row >= 0 && col >= 0 && row < maxRowIndex && col < maxColIndex;
        }
    }

    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        int n = keyboard.nextInt();
        int m = keyboard.nextInt();
        int[][] matrix = new int[n][m];
        boolean[][] visitedElements = new boolean[n][m];

        for (int row = 0; row < n; row++) {
            for (int col = 0; col < m; col++) {
                matrix[row][col] = keyboard.nextInt();
            }
        }

        int maxCounter = 0;
        for (int row = 0; row < n; row++) {
            for (int col = 0; col < m; col++) {
                if (!visitedElements[row][col]) {
                    maxCounter = Math.max(maxCounter, countAreaInMatrixDFS(row, col, matrix, visitedElements, n, m));
                }
            }
        }

        System.out.println(maxCounter);
    }

    private static int countAreaInMatrixDFS(int row, int col, int[][] matrix, boolean[][] visitedElements, int maxRowIndex, int maxColIndex) {
        Stack<Node> stack = new Stack<>();
        stack.push(new Node(row, col));
        visitedElements[row][col] = true;
        int counter = 1;

        while (stack.size() > 0) {
            Node currentNode = stack.pop();
            row = currentNode.rowIndex;
            col = currentNode.colIndex;

            Node[] neighboursIndexes = currentNode.getNeighbourNodes(maxRowIndex, maxColIndex);
            for (Node node : neighboursIndexes) {
                if (!visitedElements[node.rowIndex][node.colIndex] && matrix[row][col] == matrix[node.rowIndex][node.colIndex]) {
                    stack.push(node);
                    visitedElements[node.rowIndex][node.colIndex] = true;
                    counter++;
                }
            }
        }

        return counter;
    }
}

I tried without Node class and with BufferedReader and I still get Time limit exception.

import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.util.Stack;

    public class Main {
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String[] firstLine = br.readLine().split(" ");
            int n = Integer.parseInt(firstLine[0]);
            int m = Integer.parseInt(firstLine[1]);
            int[][] matrix = new int[n][m];
            boolean[][] visitedElements = new boolean[n][m];

            for (int row = 0; row < n; row++) {
                String[] line = br.readLine().split("\\s");
                matrix[row] = Arrays.stream(line).mapToInt(Integer::parseInt).toArray();
            }

            int maxCounter = 0;
            for (int row = 0; row < n; row++) {
                for (int col = 0; col < m; col++) {
                    if (!visitedElements[row][col]) {
                        maxCounter = Math.max(maxCounter, countAreaInMatrixDFS(row, col, matrix, visitedElements, n, m));
                    }
                }
            }

            System.out.println(maxCounter);
        }

        private static int countAreaInMatrixDFS(int row, int col, int[][] matrix, boolean[][] checkedElements, int maxRowIndex, int maxColIndex) {
            Stack<Integer[]> stack = new Stack<>();
            stack.push(new Integer[]{row, col});
            checkedElements[row][col] = true;
            int counter = 1;

            while (stack.size() > 0) {
                Integer[] elementIndexes = stack.pop();
                row = elementIndexes[0];
                col = elementIndexes[1];

                int[][] neighboursIndexes = getNeighbourNodes(row, col, maxRowIndex, maxColIndex);
                for (int[] indexes : neighboursIndexes) {
                    int neighbourRow = indexes[0];
                    int neighbourCol = indexes[1];
                    if (!checkedElements[neighbourRow][neighbourCol] && matrix[row][col] == matrix[neighbourRow][neighbourCol]) {
                        stack.push(new Integer[]{neighbourRow, neighbourCol});
                        checkedElements[neighbourRow][neighbourCol] = true;
                        counter++;
                    }
                }
            }

            return counter;
        }

        private static int[][] getNeighbourNodes(int rowIndex, int colIndex, int maxRowIndex, int maxColIndex) {
            int[][] indexes = new int[4][];

            if (indexExists(rowIndex - 1, colIndex, maxRowIndex, maxColIndex)) {
                indexes[0] = new int[]{rowIndex - 1, colIndex};
            } else {
                indexes[0] = new int[]{maxRowIndex - 1, colIndex};
            }

            if (indexExists(rowIndex + 1, colIndex, maxRowIndex, maxColIndex)) {
                indexes[1] = new int[]{rowIndex + 1, colIndex};
            } else {
                indexes[1] = new int[]{0, colIndex};
            }

            if (indexExists(rowIndex, colIndex - 1, maxRowIndex, maxColIndex)) {
                indexes[2] = new int[]{rowIndex, colIndex - 1};
            } else {
                indexes[2] = new int[]{rowIndex, maxColIndex - 1};
            }

            if (indexExists(rowIndex, colIndex + 1, maxRowIndex, maxColIndex)) {
                indexes[3] = new int[]{rowIndex, colIndex + 1};
            } else {
                indexes[3] = new int[]{rowIndex, 0};
            }

            return indexes;
        }

        private static boolean indexExists(int row, int col, int maxRowIndex, int maxColIndex) {
            return row >= 0 && col >= 0 && row < maxRowIndex && col < maxColIndex;
        }
    }
user8549135
  • 59
  • 1
  • 10
  • Is the code giving the wrong answer, or is it just taking too long? – user3386109 Dec 29 '18 at 17:31
  • no, wrong answer – user8549135 Dec 29 '18 at 17:32
  • after the 3rd test, it takes too much time, but I want to know why it is wrong for the first 2 test – user8549135 Dec 29 '18 at 17:33
  • 2
    Do you have the input and expected output for the first test? – user3386109 Dec 29 '18 at 17:35
  • Yes. I pass the first test – user8549135 Dec 29 '18 at 17:41
  • 1
    After looking at the code, my guess is that you should update `visitedElements` and the `counter` when you push the node (instead of when you pop the node). Seems to me that the same node could be pushed twice, and therefore will be double counted when it is popped twice. – user3386109 Dec 29 '18 at 17:42
  • I updated the code, but tests still couldn't be passed – user8549135 Dec 29 '18 at 17:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/185916/discussion-between-user8549135-and-user3386109). – user8549135 Dec 29 '18 at 17:57
  • I decline the invitation to chat. In order to make this question answerable, you'll need to create an example input that demonstrates the problem, and then post that example input, along with the expected output and actual output. See [mcve]. – user3386109 Dec 29 '18 at 18:00
  • I also don't know an example because the website doens't give the tests, it only shows if the aswer is right or wrong. That's why I questioned here. If I see an example, I would debug it and find the mistake. – user8549135 Dec 29 '18 at 18:05
  • Anyway, thank you for the attention. – user8549135 Dec 29 '18 at 18:06
  • Yes, I know. I'm saying that you need to experiment with examples that *you create* until you find one that gives the wrong answer. Part of software debugging is to create your own examples, especially ones that you know will test all aspects of your solution. – user3386109 Dec 29 '18 at 18:07
  • I find the solution. It seems that element with indexes [0,0] is neighbour with elements with indexes [0, matrix[0].length - 1] – user8549135 Dec 29 '18 at 18:38
  • now I have to reduce the execution time – user8549135 Dec 29 '18 at 18:39
  • 1
    Ah, very good finding the problem. The next step is to post the working code on [code review](https://codereview.stackexchange.com). They specialize in helping you improve the code. My only suggestion is that `col < matrix[row].length` should be replaced with `col < m` since you know that `matrix[row].length` is always `m`. – user3386109 Dec 29 '18 at 18:42

1 Answers1

1

In this code snippet,

if (!visitedElements[node.rowIndex][node.colIndex] && matrix[row][col] == matrix[node.rowIndex][node.colIndex]) {
    visitedElements[row][col] = true;
    counter++;
    stack.push(node);
}

you are doing visitedElements[row][col] = true; which is actually making the current index itself true again. So, it's neighbours are never getting a chance to be true and adding each other all the time. Hence, it's a time limit exceeded(as your code looks accurate).

Change visitedElements[row][col] = true; to visitedElements[node.rowIndex][node.colIndex] = true;

nice_dev
  • 17,053
  • 2
  • 21
  • 35
  • Thank you. I just didn't update the code. The problem now is the time, everything else is working fine. – user8549135 Dec 29 '18 at 19:24
  • 1
    @user8549135 So you mean the time limit is still exceeding? I suggest you to not accept the answer until it's solved. Also, I suggest you to not create a Node class and use recursion to solve this, since your time limit is pretty strict – nice_dev Dec 29 '18 at 19:31
  • 1
    @user8549135 To read input, use BuffereReader instead of Sacnner, nextInt() is a bit slow. – nice_dev Dec 29 '18 at 19:38
  • @user8549135 Are you using Java 9? I suggest you to go with Java 8,i.e, Java there. – nice_dev Dec 30 '18 at 09:57