✍️ Note
Some codes are sourced from Loony Corn’s Udemy Course (https://www.udemy.com/user/janani-ravi-2/). This post is for personal notes where I summarize the original contents to grasp the key concepts
Warming up, Recursive sense
Iterative solutions involve loops
Recursive solutions involve function that call themselves
A recursively written function takes in input, splits that input into smaller parts. Then calls itself on the smaller parts and re-combines the outputs
If the inputs to the function are too simple to split further, the recursive function will return a simple output (and not call itself)
Base case of the recursion (It prevents the recursion from going on forever)
This special case for simple inputs is called
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463332#content
Reverse String

func reverseStringIteratively(input: String) -> String {
if input.count == 1 || input.isEmpty {
return input
}
var inputArray = Array(input)
for i in 0..<input.count {
let firstIndex = i
let lastIndex = (input.count - 1) - i
if firstIndex == lastIndex {
break
}
inputArray.swapAt(firstIndex, lastIndex)
}
return String(inputArray)
}
reverseStringIteratively(input: "2AB") //BA2
Recursion approach

func reverseStringRecursively(input: String) -> String {
//Base case
if input.count == 1 || input.isEmpty {
return input
}
var inputArray = Array(input)
let first = inputArray.removeFirst()
let reversedString = reverseStringRecursively(input: String(inputArray))
return reversedString + String(first)
}
reverseStringRecursively(input: "2AB") //BA2
Exercise 1. Binary Search
Choose an element in at the mid point of a sorted list
Check whether it’s smaller than or greater than the element you are looking for
If the element at the mid point is larger than the element you are searching for
Reduce your search area to the portion where the element might be present
Base case
- There is no part of the list to search and the element has not been found
- The search element has been found at the mid point of the portion we’re searching
Recursive case
- Binary search smaller portions of the list where the element might be found
Summary
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463334#content
- By halving the search area at every step, binary search works much fatser than linear search
- The complexity of binary search is O(logN)
- The Iterative approach to binary search might perform better than the recursive approach in terms of space complexity. There is not recursive stack in the iterative approach, which means we save on some space.
Example 1. No boundary, Assumed that You will search entire input ranges
let input = Array(0...10000)
/// Return : Index
func binarySearch(input: [Int], search: Int) -> Int {
if input.isEmpty {
return -1
}
let midPoint = (input.count - 1) / 2
if input[midPoint] == search {
return input[midPoint]
}
if search > input[midPoint] {
return binarySearch(input: Array(input[midPoint..<input.count]), search: search)
}
else {
return binarySearch(input: Array(input[0..<midPoint]), search: search)
}
}
let searchedItem = binarySearch(input: input, search: 2859)
Example 2. Boundary search
let input = Array(0...10000)
/// Return : Index
/// min, max: Search Area in Input
func binarySearch(input: [Int], search: Int, min: Int, max: Int) -> Int {
//If the indices have crossed one another at the center, the term is not present in the array, return -1, base case of the recursion
if min > max {
return -1
}
let midPoint = min + (max - min) / 2
if input[midPoint] == search {
return input[midPoint]
}
//Call binary search on a smaller portion of the array depending on whether the element might be found in the first or second half of the list
if search > input[midPoint] {
return binarySearch(input: input, search: search, min: midPoint + 1, max: max)
}
else {
return binarySearch(input: input, search: search, min: min, max: midPoint - 1)
}
}
let searchedItem = binarySearch(input: input, search: 2859, min: 2800, max: 2900)
print(searchedItem)
Exercise 2. Find all subsets of a given set
Example, {1, 2, 3, 4}
- There are 2^4 subsets of this set, If we have a set of N elements the number of subsets will be 2^N
- At subsets, order is not important!
Recursive mind (Find a pattern!)
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463346#content
- Break this down, 1 element {1} -> subsets are {}, {1}
- 2 elements {1, 2} -> subsets are {}, {1}, {2}, {1, 2}
- 3 elements {1, 2, 3} -> subsets are {}, {1}, {2}, {1, 2}, {3}, {1, 3}, {2, 3}, {1, 2, 3}
func findAllSubSets(input: [Int]) -> [[Int]] {
//Base case, Break the Recursive
if input.isEmpty {
return [[]]
}
if input.count == 1 {
return [[], [input.first!]]
}
var inputArray = input
//Recursive case
let currentItem = inputArray.removeFirst()
//Reduce the inputArray at every step by removeFirst
var subsets = findAllSubSets(input: inputArray)
var currentSubSets = [[Int]]()
for subset in subsets {
var temp = subset
//Subset's items order can be ignored
temp.insert(currentItem, at: 0)
currentSubSets.append(temp)
}
for currentSubSet in currentSubSets {
subsets.append(currentSubSet)
}
return subsets
}
let subsets = findAllSubSets(input: [1, 2, 3, 4])
print(subsets)
//Prints
[[], [4], [3], [3, 4], [2], [2, 4], [2, 3], [2, 3, 4], [1], [1, 4], [1, 3], [1, 3, 4], [1, 2], [1, 2, 4], [1, 2, 3], [1, 2, 3, 4]]
Program ended with exit code: 0

Let’s take a look How to make subsets

Create the subsets of very small sets first
The for every subset, add a new element in to create newer subsets
Repeat till all elements from the original set have been used
Base Case
- When the original set is empty, only the empty set is it’s subset
Recursive Case
- Add the elements to the existing subsets to create new subsets
Since there are 2^N Subsets the complexity of this Code is O(2^N) -> This cannot be reduced further
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463346#content
Exercise 3. Find whether 2 binary trees are exactly the same
A binary tree is one where every node can have a maximum of two children – A left child and right child
Two binary trees are the same if
- Every corresponding node has the same value
- The structure of the tree at every corresponding node is the same
Base case
- A null current node on one tree should correspond to a null in the other tree
- Node values should be the same at every node
Recursive case
- Check that the sub-tree rooted at every node is the same
Time Complexity
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463352#content
- We have to visit every node in both trees so 2N nodes, the complexity is O(N)

class Tree {
let value: String
var left: Tree?
var right: Tree?
init(value: String, left: Tree? = nil, right: Tree? = nil) {
self.value = value
self.left = left
self.right = right
}
}
let treeA = Tree(value: "a")
treeA.left = Tree(value: "b")
treeA.right = Tree(value: "c")
treeA.left?.left = Tree(value: "d")
treeA.left?.right = Tree(value: "e")
treeA.right?.right = Tree(value: "f")
treeA.right?.right?.right = Tree(value: "g")
let treeB = Tree(value: "a")
treeB.left = Tree(value: "b")
treeB.right = Tree(value: "c")
treeB.left?.left = Tree(value: "d")
treeB.left?.right = Tree(value: "e")
treeB.right?.right = Tree(value: "f")
treeB.right?.right?.right = Tree(value: "g")
func isSameTree(_ a: Tree?, _ b: Tree?) -> Bool {
//Base case
if a?.left == nil, a?.right == nil, b?.left == nil, b?.right == nil, a?.value == b?.value {
return true
}
if a?.value == b?.value {
return isSameTree(a?.left, b?.left) && isSameTree(a?.right, b?.right)
}
return false
}
let isSame = isSameTree(treeA, treeB)
print(isSame) //True
Exercise 4. Build a car given all tasks and each task’s dependencies
Tip (It’s the same, How OperationQueue works, see my post)
- Set up the data structure that you plan to use to store a tasks and it’s dependencies
- Dependencies of Task “A” are all tasks which should be complete before “A” can execute.
- Paint a car, depends on build chassis of the car, The chassis needs to be ready before it can be painted
- The method should take in a list of all tasks which are needed to build a car along with their dependencies and execute every task in order to build the car
- The tasks are in any order, It’s up to you to determine some order in which it can be executed.
Tasks and dependencies
- Tasks are A, B, C, D, E, F, G, H
- B depends on A
- D depends on E
- C depends on A, B, D
- F depends on C
- An acceptable order of performing the tasks are
- E-> D -> A -> B -> C -> F
- or A -> E -> B -> D -> C -> F
- and more
Remember
- Remember that you can’t execute a task unless it’s dependencies have completed
- Store the dependencies such that they are easily accessible from a task
- Recursively execute the dependencies till you get to the task
Base case
- The current task has been executed, it’s marked done
Recursive case
- Execute dependencies before coming to the current task
Notes
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463360#content
- The tasks and it’s dependencies form a directed acyclic graph
- The graph may not be fully connected, I.E. certain tasks stand completely alone.
- It’s a topological sort.
- We have to visit every task to execute it, the complexity is O(N), where N is the number of tasks.
Example 1. Recursively run a tasks
class TaskQueue {
let value: String
var dependsOn = [TaskQueue]()
var isFinished = false
init(value: String) {
self.value = value
}
}
let taskA = TaskQueue(value: "A")
let taskB = TaskQueue(value: "B")
let taskC = TaskQueue(value: "C")
let taskD = TaskQueue(value: "D")
let taskE = TaskQueue(value: "E")
let taskF = TaskQueue(value: "F")
let taskG = TaskQueue(value: "G")
let taskH = TaskQueue(value: "H")
taskB.dependsOn = [taskA]
taskD.dependsOn = [taskE]
taskC.dependsOn = [taskA, taskB, taskD]
taskF.dependsOn = [taskC]
func buildCar(_ tasks: [TaskQueue]) {
//Base case
if tasks.isEmpty {
return
}
var remainingTasks = tasks
let dequeue = remainingTasks.removeFirst()
if dequeue.isFinished {
return buildCar(remainingTasks)
}
//[a, b, c]
// a: finish return
//Recursive case
let dependsOnUnfinishedTasks = dequeue.dependsOn.filter { $0.isFinished == false }
if !dependsOnUnfinishedTasks.isEmpty {
buildCar(dependsOnUnfinishedTasks)
}
dequeue.isFinished = true
print("\(dequeue.value)", terminator: "->")
return buildCar(remainingTasks)
}
buildCar([taskA, taskB, taskC, taskD, taskE, taskF, taskG, taskH])
//Prints
A->B->E->D->C->F->G->H
Example 2. Simplify version
class TaskQueue {
let value: String
var dependsOn = [TaskQueue]()
var isFinished = false
init(value: String) {
self.value = value
}
func run() {
if isFinished {
return
}
//Before run, recursively call run on all the dependencies of this task
for task in dependsOn {
task.run()
}
isFinished = true
print("Completed task: \(value)")
}
}
let taskA = TaskQueue(value: "A")
let taskB = TaskQueue(value: "B")
let taskC = TaskQueue(value: "C")
let taskD = TaskQueue(value: "D")
let taskE = TaskQueue(value: "E")
let taskF = TaskQueue(value: "F")
let taskG = TaskQueue(value: "G")
let taskH = TaskQueue(value: "H")
taskB.dependsOn = [taskA]
taskD.dependsOn = [taskE]
taskC.dependsOn = [taskA, taskB, taskD]
taskF.dependsOn = [taskC]
func runTask(_ tasks: [TaskQueue]) {
for task in tasks {
task.run()
}
}
runTask([taskA, taskB, taskC, taskD, taskE, taskF, taskG, taskH])
//Prints
Completed task: A
Completed task: B
Completed task: E
Completed task: D
Completed task: C
Completed task: F
Completed task: G
Completed task: H
Exercise 5. Generate anagrams of a Word
Anagrams
- A word have all the same letters of the word itself in a different order
- Consider that the letters in the word passed in are unique and that there are no spaces. I.E. It’s a word not a sentence
- The anagram need not be a valid word, we just want all the permutations of the letters.
- If all letters are unique then there are N! anagrams.
Example
- “ROAD” -> 4! Anagrams
- “ROAD”, “ORAD”, “OARD”, “RDOA”, “RAOD”, …more!
Hint
- Basic idea is the same as finding a all subsets from given a string
Break this down! (Finding a patterns!)
- Consider a word of 1 letter “A” -> Anagrams are “A”
- Consider a word of 2 letters “AB” -> Anagrams are “AB“, “BA”
- Consider a word of 3 letters “ABC” -> Anagrams are “CAB”, “ACB”, “ABC“, “CBA”, “BCA”, “BAC“
Break the word into smaller and smaller words, till we find the anagram of the smallest word.
To the smaller anagrams add in letter by letter at every possible positions
Recursively do this till we get all the letters in at every position
Base case
- The anagram of an empty string is an empty string
- The smallest word of one letter is the anagram itself
Recursive case
- Find anagrams of smaller words by removing letters from the original word
- Add the letters back one by one to every position
Complexity
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463362#content
- The number of anagrams for a word with unique letter is N! which means the complexity of this algorithm is also O(N!)
- This cannot be further optimized

func generateAnagrams(input: String) -> [String] {
//Base case
if input.count <= 1 {
return [input]
}
var inputString = input
let currentLetter = inputString.removeFirst()
var anagram = generateAnagrams(input: inputString)
var newAnagrams = [String]()
for (index, word) in anagram.enumerated() {
let wordCount = word.count
for i in 0...wordCount {
var tempWord = anagram[index]
tempWord.insert(currentLetter, at: tempWord.index(tempWord.startIndex, offsetBy: i))
newAnagrams.append(tempWord)
}
}
return newAnagrams
}
let anagrams = generateAnagrams(input: "ABC")
print(anagrams)
//Prints
["ABC", "BAC", "BCA", "ACB", "CAB", "CBA"]

Exercise 6. Implement the paint fill feature from MS Paint
Paint starts from one pixel where you click and moves outwards
All adjoining pixels with the same original color get the color fill with the new color
The color fill moves outwards till it reaches a boundary which has a different color
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463358#content

Start with one pixel which has some original color
Move outwards, If the neighboring pixels have the same original color, color them as well
Repeat till the borders are reached
What is the base case?
- The current pixel does not have the same original color, so represents a border
- The current pixel is beyond the screen boundaries
What is the recursive case?
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463358#content
- Move outward from the start pixel coloring individual pixels
var screen: [[Int]] = [
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 2, 0, 0, 0, 0, 0],
[0, 0, 1, 2, 2, 2, 0, 0, 0, 0],
[0, 0, 1, 2, 2, 2, 2, 0, 3, 3],
[0, 0, 1, 1, 1, 0, 0, 0, 3, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 3, 0],
[0, 0, 0, 5, 0, 0, 0, 0, 3, 0],
[0, 0, 5, 5, 0, 0, 0, 0, 3, 0],
[0, 5, 5, 5, 0, 0, 0, 0, 3, 0]
]
func paintFill(screen: inout [[Int]], x: Int, y: Int, originalColor: Int, newColor: Int) {
//Base Case
let width = screen.first?.count ?? 0
let height = screen.count
//Boundary check
if x < 0 || x > (width - 1) {
return
}
if y < 0 || y > (height - 1) {
return
}
//Important! y is row, x is column
let currentColor = screen[y][x]
if currentColor != originalColor {
return
}
//Paint it
screen[y][x] = newColor
//Fill neighbors pixels too
//Up, Y is Row
paintFill(screen: &screen, x: x, y: y-1, originalColor: originalColor, newColor: newColor)
//Down, Y is Row
paintFill(screen: &screen, x: x, y: y+1, originalColor: originalColor, newColor: newColor)
//Left, X is Column
paintFill(screen: &screen, x: x - 1, y: y, originalColor: originalColor, newColor: newColor)
//Right, X is Column
paintFill(screen: &screen, x: x + 1, y: y, originalColor: originalColor, newColor: newColor)
}
paintFill(screen: &screen, x: 4, y: 3, originalColor: 2, newColor: 9)
print("2 -> 9\n")
printBoard(screen)
//Results
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 9, 0, 0, 0, 0, 0],
[0, 0, 1, 9, 9, 9, 0, 0, 0, 0],
[0, 0, 1, 9, 9, 9, 9, 0, 3, 3],
[0, 0, 1, 1, 1, 0, 0, 0, 3, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 3, 0],
[0, 0, 0, 5, 0, 0, 0, 0, 3, 0],
[0, 0, 5, 5, 0, 0, 0, 0, 3, 0],
[0, 5, 5, 5, 0, 0, 0, 0, 3, 0]

Exercise 7. Find a path a rat can travel through a maze
💡 Hint! Back Tracking!
Game Rule
- Assume the maze is made up of cells with 4 walls. Each wall can have a door
- All walls do not have a door, only some do
- The rat has been placed in one of the cells, It has to make It’s way to a cell which is the “End” cell
- The rat should not go through the same cell twice while finding a path
Base case
- The rat has reached the end cell
Recursive case
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463368#content
- Keep visiting cells by passing through doors when they exist
- Do not visit cells if they are present in the current path, we don’t want the rat to move in circles

Solution 1. Using 2D Array
var maze: [[String]] = [
[" ", "G", "H", "I"],
["D", "E", "F", " "],
["A", "B", "C", " "]
]
//l: left, u: up, r: right, d: down
let door: [String: [String]] = [
"D":["l", "u", "r"],
"A": ["l", "d"],
"B": ["d"],
"C": ["d", "l", "u"],
"E": ["l"],
"F": ["d", "r"],
"G": ["l", "u"],
"H": ["u"],
"I": ["u", "r", "d"]
]
//Path: Keep track of the current path, The rat has traversed
func findPath(maze: [[String]], currentX: Int, currentY: Int, endX: Int, endY: Int, path: inout [String]) -> Bool {
//Base case
if maze.isEmpty {
return false
}
let width = maze.first?.count ?? 0
let height = maze.count
if currentX < 0, currentX >= width {
return false
}
if currentY < 0, currentY >= height {
return false
}
if endX < 0, endX >= width {
return false
}
if endY < 0, endY >= height {
return false
}
//X is column, Y is row, start X, Y means rabit's current position
let cellValue = maze[currentY][currentX]
if cellValue == " " {
return false
}
//Set visited
path.append(cellValue)
//Reached the destination
if currentX == endX, currentY == endY {
return true
}
let doors = door[cellValue]!
let allDoors = Set(["l", "r", "u", "d"])
let availableOpenedDoors = allDoors.subtracting(Set(doors))
//Check All available neighbors
for direction in availableOpenedDoors {
switch direction {
case "l":
let leftCellValue = maze[currentY][currentX - 1]
//Check If already visited or not
if path.contains(leftCellValue) == false {
//Store current path
var newPath = path
//Recursive call!
if findPath(maze: maze, currentX: currentX - 1, currentY: currentY, endX: endX, endY: endY, path: &newPath) {
//It is very important
path.removeAll()
path.append(contentsOf: newPath)
return true
}
}
case "r":
let rightCellValue = maze[currentY][currentX + 1]
if path.contains(rightCellValue) == false {
var newPath = path
if findPath(maze: maze, currentX: currentX + 1, currentY: currentY, endX: endX, endY: endY, path: &newPath) {
path.removeAll()
path.append(contentsOf: newPath)
return true
}
}
case "u":
let upCellValue = maze[currentY - 1][currentX]
if path.contains(upCellValue) == false {
var newPath = path
if findPath(maze: maze, currentX: currentX, currentY: currentY - 1, endX: endX, endY: endY, path: &newPath) {
path.removeAll()
path.append(contentsOf: newPath)
return true
}
}
case "d":
let downCellValue = maze[currentY + 1][currentX]
if path.contains(downCellValue) == false {
var newPath = path
if findPath(maze: maze, currentX: currentX, currentY: currentY + 1, endX: endX, endY: endY, path: &newPath) {
path.removeAll()
path.append(contentsOf: newPath)
return true
}
}
default:
break
}
}
print("This cell is false: \(maze[currentY][currentX])")
return false
}
var path = [String]()
let isFoundPath = findPath(maze: maze, currentX: 0, currentY: 1, endX: 3, endY: 0, path: &path)
print("\(isFoundPath) -> \(path)")
print("Finish")
//Prints Case 1
This is false: C
This is false: F
true -> ["D", "A", "B", "E", "G", "H", "I"]
Finish
//Prints Case 2
This cell is false: G
true -> ["D", "A", "B", "E", "F", "H", "I"]
Finish
Program ended with exit code: 0
Solution 2. Using Cell class
class Cell {
let id: String
let isEnd: Bool
var neighbors = [Cell]()
init(id: String, isEnd: Bool) {
self.id = id
self.isEnd = isEnd
}
}
let cellD = Cell(id: "D", isEnd: false)
let cellA = Cell(id: "A", isEnd: false)
let cellB = Cell(id: "B", isEnd: false)
let cellC = Cell(id: "C", isEnd: false)
let cellE = Cell(id: "E", isEnd: false)
let cellF = Cell(id: "F", isEnd: false)
let cellG = Cell(id: "G", isEnd: false)
let cellH = Cell(id: "H", isEnd: false)
let cellI = Cell(id: "I", isEnd: true)
cellD.neighbors = [cellA]
cellA.neighbors = [cellD, cellB]
cellB.neighbors = [cellA, cellC, cellE]
cellC.neighbors = [cellB]
cellE.neighbors = [cellG, cellF, cellB]
cellF.neighbors = [cellE, cellH]
cellH.neighbors = [cellG, cellF, cellI]
cellI.neighbors = [cellH]
func findPath(currentCell: Cell, path: inout [Cell]) -> Bool {
path.append(currentCell)
//Base case
if currentCell.isEnd {
return true
}
for neighborCell in currentCell.neighbors {
if path.contains(where: { $0.id == neighborCell.id }) == false {
var currentPath = path
if findPath(currentCell: neighborCell, path: ¤tPath) {
path.removeAll()
path.append(contentsOf: currentPath)
return true
}
}
}
return false
}
var path = [Cell]()
let isFoundPath = findPath(currentCell: cellD, path: &path)
print("\(isFoundPath) -> \(path.compactMap { $0.id })")
Exercise 8. Place 8 Queens on a Chessboard so they don’t kill each other
Rules
- Queens can move along their rows, columns and along both diagonals
- Place one queen at a time, one on each row or one on each column
- Remember to check at every step to see if the queen placed is safe, and if the remaining queens can be placed with that configuration
Solution
- Place a queen in each row or column in a safe position
- See if the remaining queens can be placed safely with the current position of the queen
- Recursively do this till the right positions for all queens have been found
- Place all 8 queens safety
Base case
- The queens have been all placed and we’re beyond the boundary of the chessboard
Recursive case
https://www.udemy.com/course/break-away-coding-interviews-1/learn/lecture/8463370#content
- Keep placing queens in different positions of the same row or column
- Check whether the remaining queens can be successfully placed

import Foundation
//https://github.com/ShawnBaek/Table
import Table
//0: Empty, 1: Queen
var chessBoard = Array(
repeating: Array(repeating: 0, count: 8),
count: 8
)
func isSafeOnLeftDiagonal(chess: [[Int]], row: Int, col: Int) -> Bool {
var r = 0
var c = 0
//Find the initial position tracing the left diagonal from the first cell in the line of the placed queen
if row > col {
r = row - col
}
else {
c = col - row
}
let columns = chess.first?.count ?? 0
let rows = chess.count
var numberOfQueen = 0
while r < rows && c < columns {
if chess[r][c] == 1 {
numberOfQueen += 1
}
r += 1
c += 1
}
return numberOfQueen <= 1
}
func isSafeOnRightDiagonal(chess: [[Int]], row: Int, col: Int) -> Bool {
let columns = chess.first?.count ?? 0
let rows = chess.count
//Start position will be top right based on current position
var r = 0
var c = columns - 1
var numberOfQueens = 0
//Option 1. I suggest calculating it and checking the start position
if (row + col < columns) {
c = min(row + col, columns - 1)
}
else {
r = (row + col) % (columns - 1)
}
while r < rows && c > 0 {
if chess[r][c] == 1 {
numberOfQueens += 1
}
r += 1
c -= 1
}
return numberOfQueens <= 1
}
func isSafePosition(chess: [[Int]], row: Int, col: Int) -> Bool {
let columns = chess.first?.count ?? 0
let rows = chess.count
//Edge case
if col < 0 || col >= columns {
return false
}
if row < 0 || row >= rows {
return false
}
//Check horizontal
for c in 0..<columns {
//Found a Queen and It's not a current position of Queen
if chess[row][c] == 1, c != col {
return false
}
}
//Check vertical
for r in 0..<rows {
if chess[r][col] == 1, r != row {
return false
}
}
//Check TopLeft -> DownRight Diagonal
if !isSafeOnLeftDiagonal(chess: chess, row: row, col: col) {
return false
}
if !isSafeOnRightDiagonal(chess: chess, row: row, col: col) {
return false
}
return true
}
func placeQueen(
chess: inout [[Int]],
col: Int
) -> Bool {
//Base case, Placed all Queens
if col >= 8 {
return true
}
for row in 0..<8 {
//Place a Queen
chess[row][col] = 1
if isSafePosition(chess: chess, row: row, col: col) {
if placeQueen(chess: &chess, col: col + 1) {
return true
}
}
//Remove Queen at this position
chess[row][col] = 0
}
return false
}
let isPlacedAllQueens = placeQueen(chess: &chessBoard, col: 0)
print(table: chessBoard)



Results

Time Complexity is O(N!), We’re trying every possible position for the queens

Leave a Reply