|
| 1 | +package com.kishan.scala.leetcode.juneChallenges |
| 2 | + |
| 3 | +import scala.collection.mutable |
| 4 | + |
| 5 | +/* |
| 6 | +* Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. |
| 7 | + A region is captured by flipping all 'O's into 'X's in that surrounded region. |
| 8 | +* |
| 9 | +* */ |
| 10 | + |
| 11 | +/* |
| 12 | +* Before: |
| 13 | +* X X X X |
| 14 | + X O O X |
| 15 | + X X O X |
| 16 | + X O X X |
| 17 | +* |
| 18 | +* After: |
| 19 | +* X X X X |
| 20 | + X X X X |
| 21 | + X X X X |
| 22 | + X O X X |
| 23 | +* |
| 24 | +* Surrounded regions shouldn’t be on the border, which means that any 'O' on the border of the board are not flipped to 'X'. |
| 25 | +* Any 'O' that is not on the border and it is not connected to an 'O' on the border will be flipped to 'X'. |
| 26 | +* Two cells are connected if they are adjacent cells connected horizontally or vertically. |
| 27 | +* */ |
| 28 | + |
| 29 | +/* |
| 30 | +* Approach: Breadth First Search or Depth First Search. |
| 31 | +* |
| 32 | +* 1. We have to go through the border of the board and check if we have any O's then we have to replace that O's with new character '*' also we have see if that 'O' has adjacent 'O' and we have to replace them with '*'. |
| 33 | +* 2. After replacing all the O's in the border and their adjacent O's connected to the border. Once again we have to go through the each element of the array and we have replace the remaining O's with 'X' and '*' with 'O'. |
| 34 | +* |
| 35 | +* */ |
| 36 | + |
| 37 | + |
| 38 | +object SurroundedRegions { |
| 39 | + def main(args: Array[String]): Unit = { |
| 40 | + // var board = Array(Array('x', 'x', 'x', 'x'), Array('x', 'o', 'o', 'x'), Array('x', 'x', 'o', 'x'), Array('x', 'o', 'x', 'x')) |
| 41 | + // var board = Array(Array('o', 'x', 'x', 'o', 'x'), Array('x', 'o', 'o', 'x', 'o'), Array('x', 'o', 'x', 'o', 'x'), Array('o', 'x', 'o', 'o', 'o'), Array('x', 'x', 'o', 'x', 'o')) |
| 42 | + var board = Array(Array('x', 'o', 'x', 'o', 'x', 'o'), Array('o', 'x', 'o', 'x', 'o', 'x'), Array('x', 'o', 'x', 'o', 'x', 'o'), Array('o', 'x', 'o', 'x', 'o', 'x')) |
| 43 | + // var board = Array(Array('x', 'o', 'x'), Array('x', 'o', 'x'), Array('x', 'o', 'x')) |
| 44 | + println("BEFORE") |
| 45 | + board.foreach(a => println(a.mkString)) |
| 46 | + solve(board) |
| 47 | + println("AFTER") |
| 48 | + board.foreach(a => println(a.mkString)) |
| 49 | + } |
| 50 | + |
| 51 | + def solve(board: Array[Array[Char]]): Unit = { |
| 52 | + if (board.length == 0 || board(0).length == 0) return |
| 53 | + val rowLength = board.length |
| 54 | + val columnLength = board(0).length |
| 55 | + for (i <- board.indices) { |
| 56 | + if (board(i)(0).toUpper == 'O') depthFirstSearch(i, 0, board) |
| 57 | + if (board(i)(columnLength - 1).toUpper == 'O') depthFirstSearch(i, columnLength - 1, board) |
| 58 | + } |
| 59 | + |
| 60 | + for (j <- board(0).indices) { |
| 61 | + if (board(0)(j).toUpper == 'O') depthFirstSearch(0, j, board) |
| 62 | + if (board(rowLength - 1)(j).toUpper == 'O') depthFirstSearch(rowLength - 1, j, board) |
| 63 | + } |
| 64 | + |
| 65 | + for (i <- board.indices) { |
| 66 | + for (j <- board(0).indices) { |
| 67 | + if (board(i)(j).toUpper == 'O') { |
| 68 | + board(i)(j) = 'X' |
| 69 | + } else if (board(i)(j) == '*') { |
| 70 | + board(i)(j) = 'O' |
| 71 | + } |
| 72 | + } |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + def depthFirstSearch(i: Int, j: Int, board: Array[Array[Char]]): Unit = { |
| 77 | + if (i < 0 || i > board.length - 1 || j < 0 || j > board(i).length - 1) return |
| 78 | + if (board(i)(j).toUpper == 'O') board(i)(j) = '*' |
| 79 | + if (i > 0 && board(i - 1)(j).toUpper == 'O') depthFirstSearch(i - 1, j, board) |
| 80 | + if (i < board.length - 1 && board(i + 1)(j).toUpper == 'O') depthFirstSearch(i + 1, j, board) |
| 81 | + if (j > 0 && board(i)(j - 1).toUpper == 'O') depthFirstSearch(i, j - 1, board) |
| 82 | + if (j < board(0).length - 1 && board(i)(j + 1).toUpper == 'O') depthFirstSearch(i, j + 1, board) |
| 83 | + } |
| 84 | + |
| 85 | + |
| 86 | + def solveBFS(board: Array[Array[Char]]): Unit = { |
| 87 | + if (board.length == 0 || board(0).length == 0) return |
| 88 | + var queue: mutable.Queue[(Int, Int)] = mutable.Queue() |
| 89 | + for (i <- board.indices) { |
| 90 | + if (board(i)(0) == 'O') BFS(i, 0, board) |
| 91 | + if (board(i)(board(0).length - 1) == 'O') BFS(i, board(0).length - 1, board) |
| 92 | + } |
| 93 | + |
| 94 | + for (j <- board(0).indices) { |
| 95 | + if (board(0)(j) == 'O') BFS(0, j, board) |
| 96 | + if (board(board.length - 1)(j) == 'O') BFS(board.length - 1, j, board) |
| 97 | + } |
| 98 | + |
| 99 | + for (i <- board.indices) { |
| 100 | + for (j <- board(0).indices) { |
| 101 | + if (board(i)(j) == '*') board(i)(j) = 'O' else if (board(i)(j) == 'O') board(i)(j) = 'X' |
| 102 | + } |
| 103 | + } |
| 104 | + |
| 105 | + def BFS(i: Int, j: Int, array: Array[Array[Char]]): Unit = { |
| 106 | + if (i < 0 || i > array.length - 1 || j < 0 || j > array(0).length - 1) return |
| 107 | + if (array(i)(j) == 'O') queue.enqueue((i, j)) |
| 108 | + while (queue.nonEmpty) { |
| 109 | + val position = queue.dequeue() |
| 110 | + array(position._1)(position._2) = '*' |
| 111 | + if (position._1 > 0 && array(position._1 - 1)(position._2) == 'O' && !queue.contains((position._1 - 1, position._2))) queue.enqueue((position._1 - 1, position._2)) |
| 112 | + if (position._1 < array.length - 1 && array(position._1 + 1)(position._2) == 'O' && !queue.contains((position._1 + 1, position._2))) queue.enqueue((position._1 + 1, position._2)) |
| 113 | + if (position._2 > 0 && array(position._1)(position._2 - 1) == 'O' && !queue.contains((position._1, position._2 - 1))) queue.enqueue((position._1, position._2 - 1)) |
| 114 | + if (position._2 < array(0).length - 1 && array(position._1)(position._2 + 1) == 'O' && !queue.contains((position._1, position._2 + 1))) queue.enqueue((position._1, position._2 + 1)) |
| 115 | + } |
| 116 | + } |
| 117 | + } |
| 118 | +} |
0 commit comments