Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions src/NQueens.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import java.util.ArrayList;
import java.util.List;

public class NQueens {

private List<List<String>> solutions;

/*
* Time Complexity:
* - Each placement calls isValid() which scans up to O(n) vertically and diagonally -> O(n)
* - Rough upper bound: O(n! * n)
* Space Complexity:
* - O(n^2) for the board + O(n) recursion depth
*/
public List<List<String>> solveNQueens(int n) {
solutions = new ArrayList<>();
boolean[][] board = new boolean[n][n]; // true means a queen is placed
backtrack(board, 0, n);
return solutions;
}

/*
Place a queen in one row and recursively slow the other rows
*/
private void backtrack(boolean[][] board, int row, int n) {
// Base case: if we've placed queens in all rows, we found a valid solution
if (row == n) {
solutions.add(buildSolution(board, n));
return;
}

// Try placing a queen in every column of the current row
for (int col = 0; col < n; col++) {
if (isValid(board, row, col, n)) {
// Choose
board[row][col] = true;

// Explore
backtrack(board, row + 1, n);

// Un-choose (backtrack)
board[row][col] = false;
}
}
}

/*
Converts the boolean board into the required List<String> representation
*/
private List<String> buildSolution(boolean[][] board, int n) {
List<String> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < n; j++) {
sb.append(board[i][j] ? 'Q' : '.');
}
list.add(sb.toString());
}
return list;
}

/*
* Checks if placing a queen at (row, col) is safe.
* Since we place queens row-by-row from top to bottom, we only need to check:
* 1) same column above
* 2) upper-left diagonal
* 3) upper-right diagonal
*/
private boolean isValid(boolean[][] board, int row, int col, int n) {
//Check same column (above rows)
for (int r = row; r >= 0; r--) {
if (board[r][col]) return false;
}

// Check upper-left diagonal
for (int r = row, c = col; r >= 0 && c >= 0; r--, c--) {
if (board[r][c]) return false;
}

// Check upper-right diagonal
for (int r = row, c = col; r >= 0 && c < n; r--, c++) {
if (board[r][c]) return false;
}

return true;
}

// Test
public static void main(String[] args) {
NQueens solver = new NQueens();

int n = 4;
List<List<String>> res = solver.solveNQueens(n);

System.out.println("n = " + n);
System.out.println("Number of solutions: " + res.size());
System.out.println();

// Print all solutions
int solNum = 1;
for (List<String> sol : res) {
System.out.println("Solution " + solNum++ + ":");
for (String row : sol) {
System.out.println(row);
}
System.out.println();
}
}
}
81 changes: 81 additions & 0 deletions src/WordSearch.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
public class WordSearch {
// Directions: up, down, right, left
private int[][] dirs;
private int m, n;
/*
Time Complexity - O(m * n * 4^L) where L = word.length()
Space Complexity - O(L) recursion stack in the worst case.
*/
public boolean exist(char[][] board, String word) {
this.dirs = new int[][]{{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
this.m = board.length;
this.n = board[0].length;

// Try starting the DFS from every cell in the board
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// if DFS succeeds, return true immediately
if (dfs(board, i, j, word, 0)) {
return true;
}
}
}
return false;
}

/**
* DFS (backtracking) to match word[idx...] starting from board[i][j].
*/
private boolean dfs(char[][] board, int i, int j, String word, int idx) {
// Base case: we've matched all characters
if (idx == word.length()) return true;

// Out of bounds or already visited
if (i < 0 || j < 0 || i == m || j == n || board[i][j] == '#') return false;

// Current cell must match the current character in word
if (board[i][j] != word.charAt(idx)) return false;

// Mark as visited (so we don't reuse the same cell in this path)
char saved = board[i][j];
board[i][j] = '#';

// Explore 4 neighbors
for (int[] dir : dirs) {
int x = i + dir[0];
int y = j + dir[1];

if (dfs(board, x, y, word, idx + 1)) {
// Restore before returning
board[i][j] = saved;
return true;
}
}

// Backtrack: restore the original value before returning
board[i][j] = saved;
return false;
}

// Testing
public static void main(String[] args) {
WordSearch ws = new WordSearch();

char[][] board1 = {
{'A','B','C','E'},
{'S','F','C','S'},
{'A','D','E','E'}
};

System.out.println(ws.exist(board1, "ABCCED")); // true
System.out.println(ws.exist(board1, "SEE")); // true
System.out.println(ws.exist(board1, "ABCB")); // false

char[][] board2 = {
{'C','A','A'},
{'A','A','A'},
{'B','C','D'}
};
System.out.println(ws.exist(board2, "AAB")); // true
}
}