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
112 changes: 112 additions & 0 deletions N-Queens.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
//
// N-Queens.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 4/7/26.
//

/*
In backtracking - time complexity will be exponential
/*
In first row, we will try placing the queen at position 1, then check in row2, where it can be placed. If it can't be placed anywhere and all possible positions are exhausted, then backtrack the action taken in row 1. Place queen in row1 at some other square.
*/
time complexity -
in top row - we have n options
in 2nd row -> (n-2) options - let's consider it's n
.... and so on -> on nth row -> we have n options

so total time compelxity - n^n

Now, if we consider the exact options then
n * (n - 2) * (n - 4) * ....
for worst case, let's make it n * (n - 1) * (n - 2)....
Hence, it will be n!

If we consider isValid function then n * n! worst case - it could go n, from bottom to 0th...
But still n!

*/


class NQueens {
func solveNQueens(_ n: Int) -> [[String]] {
var result = [[String]]()
var matrix = Array(repeating: Array(repeating: false, count: n), count: n)
var s = ""
findPositions(n, matrix: &matrix, i: 0, result: &result)
return result
}

/*
We have to make for loop on columns. We need to backtrack on the position of rows.
Hence,
*/
func findPositions(_ n: Int, matrix: inout [[Bool]], i: Int, result: inout [[String]]) {
//base
if (i == n) {
//means has passed the boundary of the matrix, then
var path = [String]()
for r in 0..<matrix.count {
var s = ""
for c in 0..<matrix[0].count {
if (matrix[r][c]) {
s += "Q"
} else {
s += "."
}
}
path.append(s)
}
result.append(path)
return
}

//logic

for j in 0..<n {
//if the index is valid or not, if it is valid the only place the queen or else leave
if (isValid(matrix: matrix, i: i, j: j)) {

matrix[i][j] = true
findPositions(n, matrix: &matrix, i: i + 1, result: &result)
matrix[i][j] = false
}
}
}

func isValid(matrix: [[Bool]], i: Int, j: Int) -> Bool {
var r = i
var c = j
//if vertically, until the top row, any queen is placed then return false
while (r >= 0) {
if (matrix[r][c]) {
return false
}
r -= 1
}

r = i
c = j
//if diagonal left, until the top rw, any queen is placed, return false
while (r >= 0 && c >= 0) {
if (matrix[r][c]) {
return false
}
r -= 1
c -= 1
}

r = i
c = j
//if diagonal right, until the right, any queen is placed then retuen false
while (r >= 0 && c < matrix.count) {
if (matrix[r][c]) {
return false
}
r -= 1
c += 1
}

return true
}
}
123 changes: 123 additions & 0 deletions WordSearch.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//
// WordSearch.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 4/8/26.
//

class WordSearch {

init() {
let isPresent = exist([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCCED")
print("isPresent \(isPresent)")
}

var isPresent = false

//DFS with backtracking
/*
DFS - time complexity - at first level 4 options. 2nd level options - only 3 optons. We are coming from 1 path. So 3^l, l - length of the word
Initially we will try to find the first character by 2 loops on m * n
so, total time complexity - m * n * 3^l
*/
/*
With BFS -> has difficulty in tracking from which path we came and where to backtrack.
The advantage of DFS is single path - any. we can come back from a single path when backtracking.
BOAT tese case - AAAAAAAAB
/*

*/
*/
func exist(_ board: [[Character]], _ word: String) -> Bool {
var board = board
var visited = Array(repeating: Array(repeating: false, count: board[0].count), count: board.count)
for i in 0..<board.count {
for j in 0..<board[0].count {
helper(&board, word, level: 0, i: i, j: j, visited: &visited)
}
}
return isPresent
}
func helper(_ board: inout [[Character]], _ word: String, level: Int, i: Int, j: Int, visited: inout [[Bool]]){
let wordArr = Array(word)

if (wordArr[level] != board[i][j]) {
return
}

if (level == word.count - 1) {
isPresent = true
return
}
if (board[i][j] == wordArr[level]) {
//action
board[i][j] = "#"

//recurse
var dirs = [[1,0], [-1, 0], [0,1], [0, -1]]
for dir in dirs {
let nr = i + dir[0]
let nc = j + dir[1]
if (nr < 0 || nc < 0 || nr == board.count || nc == board[0].count) {
continue
}

// if (visited[nr][nc] == false) {
if (board[nr][nc] != "#") {
helper(&board, word, level: level + 1, i: nr, j: nc, visited: &visited)
}
}
//backtrack
board[i][j] = wordArr[level]
}
}

//MARK: Bool based
/*
(m*n) 3^l
space complexity - O(1)
*/
func existBoolBased(_ board: [[Character]], _ word: String) -> Bool {
var board = board
let wordArr = Array(word)
for i in 0..<board.count {
for j in 0..<board[0].count {
if (helperBoolBased(&board, wordArr, level: 0, i: i, j: j)) {
return true
}
}
}
return false
}

func helperBoolBased(_ board: inout [[Character]], _ wordArr: [Character], level: Int, i: Int, j: Int) -> Bool {

//when all the characters are finished
if (level == wordArr.count) {
return true
}
if (i < 0 || j < 0 || i == board.count || j == board[0].count) {
return false
}

if (board[i][j] == wordArr[level]) {
//action
board[i][j] = "#"

//recurse
var dirs = [[1,0], [-1, 0], [0,1], [0, -1]]
for dir in dirs {
let nr = i + dir[0]
let nc = j + dir[1]
if (helperBoolBased(&board, wordArr, level: level + 1, i: nr, j: nc)) {
return true
}
}
//backtrack
board[i][j] = wordArr[level]
}
return false
}


}