https://leetcode.com/problems/surrounded-regions/
I read through the editorial, and coded up a solution. Everything makes sense, and locally my code changes the board to the expected output, yet when I paste the code to Leetcode, my board stays the same. I used their debugger and placed a breakpoint at line 24, sure enough, I don't see any changes on the board.
Not sure where else to ask this, so I'm sorry if this isn't the right place.
The following is my code:
import java.util.Arrays;
class Solution {
private int ROWS;
private int COLS;
public void solve(char[][] board) {
ROWS = board.length;
COLS = board[0].length;
// parse left and right borders
for (int i = 0; i < ROWS; i++) {
DFS(board, i, 0); // left border
DFS(board, i, ROWS - 1); // right border
}
// parse top and bottom borders
for (int j = 0; j < COLS; j++) {
DFS(board, 0, j); // top border
DFS(board, COLS - 1, j); // bottom border
}
// after parsing, we end up with x, o, e board. Pass through it, and change
// 1) o to x
// 2) e to o
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (board[i][j] == 'o') {
board[i][j] = 'x';
}
else if (board[i][j] == 'e') {
board[i][j] = 'o';
}
}
}
}
private void DFS(char[][] board, int i, int j) {
if (i >= ROWS || j >= COLS) return; // bounds
if (board[i][j] != 'o') return;
board[i][j] = 'e'; // temporary marker, to help identify border-connected cells
// go right
DFS(board, i, j + 1);
// go down
DFS(board, i + 1, j);
// go left
DFS(board, i, j - 1);
// go up
DFS(board, i - 1, j);
}
public static void main (String[] args) {
char[][] test1 = new char[][] {
{'x','x','x','x'},
{'x','o','o','x'},
{'x','x','o','x'},
{'x','o','x','x'}
};
new Solution().solve(test1);
Arrays.stream(test1).forEach(e -> System.out.println(Arrays.toString(e)));
}
}
Running it locally, I get exactly what's expected in the console
[x, x, x, x]
[x, x, x, x]
[x, x, x, x]
[x, o, x, x]
Your main issue is that your code assumes a matrix of lowercase O and X, while the LeetCode problem gives you matrix of uppercase O and X. Since 'o' is not the same as 'O', and 'x' is not the same as 'X', your code doesn't solve the LeetCode problem.
In the future, I recommend using copy-and-paste when copying test-cases, so that you get them exactly right.
Since I'm here, I'll also point out two other issues with your code:
Your depth-first search has logic to ensure that you never walk off the bottom or right edge of the grid, but it doesn't do anything to ensure that you never walk off the top or left edge. (Your test-case doesn't trigger that, because there are no O's along the top or left edge that test-case.)
Your code has various comments that talk about "parsing", when in fact you're doing no such thing. (See https://www.google.com/search?q=parsing.) That won't affect your code's behavior, obviously, but it can confuse human readers, or at least make you look a bit clueless. I'd suggest writing (for example) // find all O's connected to left and right borders, and change them to E's.
Related
So the goal is to print all possible numbers whose digits can be formed by a sequence of adjacent characters on a board using dfs. By adjacent I mean next to each other, either vertically, horizontally or diagonally. There are 8 total movement directions. Ex: the board below
1 2
3 4
To make it simpler let's say that we always have to start at row0 column0, which is 1. So the possible numbers are: 1, 12, 13, 14, 123, 124, 132, 134, 142, 143, 1234, etc (this case is pretty trivial because all numbers are directly adjacent to each other)
So I have the following code:
static char[][] grid;
static int rows;
static int columns;
public static void main(String[] args) {
//test grid. made it small so that solutions are easy to count
grid = new char[][]{
new char[]{'1', '2'},
new char[]{'3', '4'},
};
rows = grid.length;
columns = grid[0].length;
dfs(0, 0, new boolean[rows][columns], new StringBuilder());
}
public static void dfs(int row, int col, boolean[][] visited, StringBuilder builder){
visited[row][col] = true;
builder.append(grid[row][col]);
System.out.println(builder.toString());
//the 2 loops are for the 8 movement directions
for(int x = -1; x <= 1; x++){
for(int y = -1; y <= 1; y++){
//index bounds check
if((row + x >= 0) && (row + x < rows) && (col + y >= 0) && (col + y < columns)){
if(!visited[row + x][col + y]){
dfs(row + x, col + y, visited, builder);
// I tried changing it so that it passes a COPY of 'visited' and 'builder',
// but output still the same
dfs(row + x, col + y, Arrays.copyOf(visited, visited.length), new StringBuilder(builder));
}
}
}
}
}
My code's output is not right. Here's what it prints:
1
12
123
1234
Those numbers are part of the solution, but are a lot more numbers than that. The error probably has something to do with passing the same object into the recursive dfs() call, but I tried changing it so that it only copies the object, and it still gives the same output.
Any ideas?
You should be able to do achieve the expected output without creating a copy of the visited matrix.
The important thing is to set visited[row][col] to false after each COMPLETE visit down a path.
Example:
Let's say you've traversed '12' and now have '3' and '4' left to visit. In the current state, visited matrix's values for '1' and '2' are set to true and for '3' and '4' are set to false. Once you have finished generating all strings that begin with '12', you will start looking at all strings beginning with '13'.
But look at what happens here! You had set the visited value of '2' to true, and so no future strings containing '2' will ever be generated.
This is why you must set visited[row][col] to false after you are done generating all paths from that point onward.
To truly understand this, trace your code with pen and paper and you will remember it better.
Note:
In reality, in the example described above, you will never generate strings beginning with '13' because visited[1][1] would have been set to true before and so 3 would have never been reached again. I ignored that fact to illustrate a point.
Why do I suggest not making a deep copy of visited each recursive call? Simple, to save time and space. Each call will take O(m*n) space and time to generate and store a new visited matrix.
Here is one variant of the correct code:
import java.util.*;
public class DFS{
static char[][] grid;
static int rows;
static int columns;
public static void main(String[] args) {
//test grid. made it small so that solutions are easy to count
grid = new char[][]{
new char[]{'1', '2'},
new char[]{'3','4'},
};
rows = grid.length;
columns = grid[0].length;
ArrayList<String>list = new ArrayList<>();
dfs(0, 0, new boolean[rows][columns], new StringBuilder());
//System.out.println(list);
}
public static void dfs(int row, int col, boolean[][] visited, StringBuilder builder){
visited[row][col] = true;
builder.append(grid[row][col]);
System.out.println(builder);
for(int x = -1; x <= 1; x++){
for(int y = -1; y <= 1; y++){
//index bounds check
if((row + x >= 0) && (row + x < rows) && (col + y >= 0) && (col + y < columns)){
if(!visited[row + x][col + y]){
dfs(row + x, col + y, visited, builder);
}
}
}
}
visited[row][col]=false;
builder.deleteCharAt(builder.length()-1);
}
}
EDIT: I forgot to highlight the last line of code added where I delete the last character of the current StringBuilder. This is the backtracking bit so that after all '12xx' strings are generated, you delete '2', replace it with '3' and now start exploring the '13xx' family of strings.
The problem is that there is no output happening, not an extra println(). This is odd, because doing this programming without a static SIZE var, it works just fine.
public class SlashFigure2
{
public static final int SIZE = 4;
public static void main(String[] args)
{
for(int i = 1; i <= SIZE; i++)
{
for(int j = 1; j <= 2 * i - (2 * SIZE + 2); j++)
{
System.out.print("\\");
}
for(int j = 1; j <= -4 * i + (-4 * SIZE + 2); j++)
{
System.out.print("!");
}
for(int j = 1; j <= 2 * i - (2 * SIZE + 2); j++)
{
System.out.print("/");
}
System.out.println();
}
}
}
In case anyone needs it, here's what the program prints:
!!!!!!!!!!!!!!
\\!!!!!!!!!!//
\\\\!!!!!!////
\\\\\\!!//////
EDIT: Here's what the site keeps saying is the error
EDIT 2:
The site is practiceit.csu.washington.edu
Here is the question's wording:
Modify your DollarFigure program from the previous exercise to become
a new program called DollarFigure2 that uses a global constant for the
figure's height. (You may want to make loop tables first.) The
previous output used a constant height of 7. The outputs below use a
constant size of 3 (left) and 5 (right)
Here are the outputs below they are talking about
(You must solve this problem using only ONE public static final
constant, not multiple constants; and its value must be used in the
way described in this problem.)
Simply do this:
if (i != SIZE) {
System.out.println();
}
Because i will be equal to SIZE in the last iteration, and you want to skip the println() in that case.
UPDATE
From the comments and the image, it's clear that you're not supposed to define SIZE as a constant, apparently you should be able to pass n as a parameter to your program, it's not a hardcoded value. Check the rules of the "site" you keep referring to, how's the input supposed to be received?
You can make this change in your code to make it work.You should not execute the statement when i is equal to SIZE
if(i<SIZE){
System.out.println();
}
Somewhat Jeopardy to find out the actual problem/quest you want to solve by algorithmically print a specific ASCII-art only denoted by a constant ROW-size (e.g. 4 or 6 as depicted on the attached image).
Tests & sample output
Derived specification
Draw a specific figure varying only in its height:
only single parameter is passed: rows of ASCII-art to draw
figure to draw should resemble a downward-arrow
bordered by double-slashes left and right, i.e. \\ respective //
no border/slashes on the first row
inner/rest of the rows filled with exclamation-marks !!
at least 2 exclamation-marks !! on the inner last row
Java method with single parameter: ROWS
private static void drawAsciiArt(int rows) {
int columns = (rows-1)*4+2;
for(int i = 1; i <= rows; i++) {
int borderSize = (i-1)*2;
int fillSize = columns - borderSize*2;
for(int j = 1; j <= borderSize; j++) {
System.out.print("\\");
}
for(int j = 1; j <= fillSize; j++) {
System.out.print("!");
}
for(int j = 1; j <= borderSize; j++) {
System.out.print("/");
}
if (i < rows) {
System.out.println();
} // if not last row
} // end of row-loop
}
Try this online
Figured it out! It turns out that for both the '\' and '/' characters, I didn't need to use that (x * SIZE + y) formula after all. They both needed the regular formula while the '!' is the only character that needed the SIZE formula
public class SlashFigure2
{
public static final int SIZE = 4;
//program works no matter what value SIZE holds
public static void main(String[] args)
{
for(int i = 1; i <= SIZE; i++)
{
for(int j = 1; j <= 2 * i - 2; j++)
{
System.out.print("\\");
}
//note the SIZE formula in here
for(int j = 1; j <= -4 * i + (4 * SIZE + 2); j++)
{
System.out.print("!");
}
for(int j = 1; j <= 2 * i - 2; j++)
{
System.out.print("/");
}
System.out.println();
}
}
}
It's my job to test exercises for other students. Today I got a really difficult one (at least for me) and I'm not sure if I'm just a blockhead right now.
I got a 2D char Array and 3 Strings which I have to find in there. The words can span horizontal, vertical, and diagonal; forwards or backwards. The problem: I'm not allowed to use any methods, everything has to be inside the main method.
I don't find a way which doesn't have like < 10 loops. Do you have a smart idea?
I mean, this is the obvious way, of course…
Comparisons could be slightly sped up with Boyer-Moore or similar.
for row in haystack:
for character in row:
#check if pattern or reversed pattern matches
for column in haystack:
for character in column:
#check if pattern or reversed pattern matches
for positively-sloped-diagonal in haystack:
for character in diagonal:
#check
for negatively-sloped-diagonal in haystack:
for character in diagonal:
#check
Depending on the exact parameters, it could be a little bit less braindead to do something like:
for each pattern:
for each slot in the array:
for horizontal in [-1, 0, 1]:
for vertical in [-1, 0, 1]:
if horizontal == vertical == 0:
pass
for n in range(pattern.length):
if pattern[n] != haystack[row + n * vertical][column + n * horizontal]
break
#Pattern found
#Pattern not found
You can recursively call the main method to search forward, backward, up, down, left-up/down diagonal, and right-up/down diagonal.
if (arg[2] == array.length && arg[3] == array.length)
return 0;
if (firstTimeMainFunctionCalled) {
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[0].length; j++) {
// Only make recursive call when you are
// on the outer edge of the 2D array
if (i == 0 || j == 0) {
main(1, 0, i, j);
main(0, 1, i, j);
main(1, 1, i, j);
main(-1, 0, i, j);
main(0, -1, i, j);
main(-1, -1, i, j);
main(1, -1, i, j);
main(-1, 1, i, j);
}
}
}
int rowInc = arg[0];
int colInc = arg[1];
int curRow = arg[2];
int curCol = arg[3];
int str1Place = 0;
int str2Place = 0;
int str3Place = 0;
while (curRow >= 0 && curCol >= 0 && curRow < array.length && curCol < array[0].length) {
if (array[curRow][curCol] == str1[str1Place])
str1Place++;
else
str1Place = 0;
if (str1Place == str1.length)
// Found str1
// Do the same for str2 and str3
curRow += rowInc;
curCol += colInc;
}
This is a very crude solution and can be improved a whole lot, you obviously have to call the main method appropriately by turning the arguments into a list of strings but it should give you somewhere to start. You can improve this using dynamic programming, you can also backtrack to do something with the string once you find it. Also, as you can see the nested loop doesn't need to be nested.
Pardon my pseudocode :)
I need to create a triangle of at least 5 rows.
I know how to create the top and bottom but I can't figure out the middle part. I don't know how to find the algorithms to express the changes in spaces added to each subsequent row following the first. Can I get hints?
This problem is from my teacher.
You can think as this: suppose you want to paint a triangle of R rows. Then, for example, for R = 5, you would paint something like this:
*
**
***
****
*****
which is isosceles (and also right :)). So, the basic observation is that if the current row has i stars, the previous has i-1 and the next one i+1. So, you can initialize a variable with the current row, which also holds the number of stars to paint. Something like this:
int R = (...) // get this parameter from user or whatever
int r = 1; // current row, and number of stars to paint in the current line
while (r <= R) { // while you haven't painted more than R rows
int i = 1; // counter for painting r stars
while (i <= r) {
System.out.print('*');
++i; // next star
}
System.out.println(); // go to the next row (or line)
}
Hope it helped.
Edit: if your teacher is as skeptical as RealSkeptic down there in the comments, you can use the following observation. Suppose you want to paint a triangle like this:
*
**
***
**
*
That is, an isosceles triangle rotated, such that the len of the equal sides is R. For the example, R = 3. You can see that painting such triangle is like painting a rectangle with 2 different kinds of cells, like the following:
*00 (1 star, 2 zeroes)
**0 (2 stars, 1 zero)
*** (3 stars)
**0 (2 stars, 1 zero)
*00 (1 star, 2 zeroes)
You can note that the sequence grows and then decreases back. You can simulate such behavior with a counter that starts in negative values and runs until the same positive value. The code would be something like:
int R = (...) // get this parameter from user or whatever
int r = -R+1;
while (r <= R-1) {
int i = 1;
int rabs = r;
if (rabs < 0) rabs = -rabs; // take only the positive value
while (i <= R-rabs) {
System.out.print('*');
++i; // next star
}
System.out.println(); // go to the next row (or line)
++r;
}
EDIT2: watching the triangle you added to your question (which you should have added since the very beginning), you can follow the reasoning of the previous edit on the number of stars and spaces per row, and reach to a code like the following:
int R = (...) // get this parameter from user or whatever
int r = 1;
while (r < R) {
int i = 1;
while (i <= R-r) {
System.out.print(" ");
++i;
}
if (r>1) System.out.print("*"); // because there's only 1 star on first row always
i = 1;
while (i <= 2*r-3) { // the amount of spaces you need to paint
System.out.print(" ");
++i;
}
System.out.println("*");
++r;
}
// paint the last row separately
int last = R+R-1;
while (last > 0) {
System.out.print("*");
--last;
}
Good luck.
EDIT3: maybe this approach is more verbose, but easier to understand. The point is to save in variables how many spaces you need to print before the first star, and after the first star, in each row. The code would be like this:
int R = (...) // get this number from user or whatever
int spacesBeforeFirstStar = R-1;
int spacesAfterFirstStar = -1;
int r = 1;
while (r <= R) {
int i = 1;
while (i <= spacesBeforeFirstStar) { // paint the first spaces
System.out.print(" ");
++i;
}
if (r!=1) System.out.print("*"); // if not the first row, paint the first star
i = 1;
while (i <= spacesAfterFirstStar) { // paint the spaces inside the triangle
if (r==R) // if we are in the last row
System.out.print("*"); // we paint stars instead spaces
else
System.out.print(" "); // otherwise, we just paint spaces
++i;
}
System.out.println("*"); // print the second star
spacesBeforeFirstStar -= 1; // in the next row, we paint one space less
spacesAfterFirstStar += 2; // in the next row, we paint two spaces more
++r; // go to the next row
}
Here,
int n = 6;
int row = 0;
int col = 0;
int space = 0;
for(row = 1; row < n; row++) {
for(space = 0; space < n - row; space++) {
System.out.print(" ");
}
for(col = 1; col <= row; col++) {
if(row == (n-1)) {
System.out.print("* ");
} else {
if(col == 1 || col == row) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
}
System.out.println();
}
It prints out the following:
As you can see it's an equilateral triangle. You can modify the code in the loop using conditional statements so that when it reaches at the time of creating the base for the triangle it will print this
I have left that one for you to ponder upon.
I'm trying to print out an indicator of coordinates on a 2D array...
There is another class that I've used to instantiate objects on the array.
I need to the store coordinates in two (local?) variables, and then display the position of those coordinates in the printed array. (that has already been instantiated with various objects)
This is a snippet of code I have so far, but I can't get the 'C' to print in the right spot on the array. The few options that I tired, either doesn't print it at all, or prints the 'C' in the top left hand corner.
This is one option that I've tired: This option doesn't print the 'C' at all.
private int cX=0;
private int cY=0;
//Randomly set coordinates on array.
for(int i=0; i<array.length; i++){
for(int j=0; j<array[i].length; j++){
int x = randGen.nextInt(9);
int y = randGen.nextInt(9);
if (array [x][y].display()=='.'){
x=cX;
y=cY;
}
}
}
// print array
private void displayArray()
{
for (int i = 0; i < array.length; i++){
for (int j = 0; j < array[i].length; j++){
if ((array [i][j].display()==cX)&&
(array [i][j].display()==cY))
System.out.print("C");
System.out.print(board [i][j].display()+"\t")
}
System.out.println("\n");
}
}
If I understood you right, you'd like to save coordinates to some kind of data structure and later display them?
Wouldn't it be suitable to create a class for this purpose? E.g.
A class called Coordinator, that holds the X & Y values.
Later create a object of the class you've made with X & Y values and put it to a ArrayList.
Code Example:
//Creating the a object holding 2 values
Coordinator cords = new Coordinator(randGen.nextInt(9), randGen.nextInt(9));
//Putting in the object to the data structure
List<Coordinator> list = new ArrayList<>();
list.add(cords);
The explanation and code example should help you solve this issue on your own hopefully.
This option doesn't print the 'C' at all.
Your current code example will indeed never print a 'C'.
for (int j = 0; j < array[i].length; j++){
if ((array [i][j].display()==cX)&&
(array [i][j].display()==cY))
This if condition will be true only if cX equals cY and both are equal to the ascii code value assigned to the array (for '.' this is the value 46). But you may just want to find the cX,cY position and print a 'C'. You should try to campare your position (cX, cY) with the current i and j values.
if ((i==cX)&&(j==cY))
prints the 'C' in the top left hand corner
You never change the content of array at the position. You set x and y which will be overwritten and are later no accessible
int x = randGen.nextInt(9);
int y = randGen.nextInt(9);
if (array [x][y].display()=='.'){
x=cX;
y=cY;
}
Do you want to find a random position for your 'C' to appear, like in a board game?
Then you need to assign your found x and y coordinate to cX and cY. The right value gets assigned to the left variable.
cX = x;
cY = y;
I hope I understood you right and this helps.
For completeness: I think I worked it out. (Well it seems to be working anyway).
Thanks for the help!
private int cX=0;
private int cY=0;
//Randomly set coordinates on the array.
for(int i=0; i<1; i++){
int x = randGen.nextInt(9);
int y = randGen.nextInt(9);
if (board [x][y].display()=='.'){
CX=x;
CY=y;
}
}
//Print array
private void displayArray(){
for (int i = 0; i < board.length; i++){
for (int j = 0; j < board[i].length; j++){
if ((i==CX)&&(j==CY))
System.out.print("C"+"\t");
else
System.out.print(board [i][j].display()+"\t");
}
System.out.println("\n");
}
}
private double[][] mLatLng = {
{19.01062463, 73.01141475},
{19.02369039, 73.00778391},};
public void onMapReady(GoogleMap googleMap) { googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_icon);
for (int i = 0; i < mLatLng.length; i++) {
for (int j = 0; j < mLatLng[i].length; j++) {
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(mLatLng[i][j], mLatLng[i][j]))
.title("Location" + i).icon(bitmapDescriptorFromVector(context,R.drawable.ic_icon)));