# Backtracking: Famous Problems --- title: Agenda description: duration: 300 card_type: cue_card --- 1. N Queen 2. Sudoku 3. Word Break Problem --- title: Problem 1 N Queen description: duration: 600 card_type: cue_card --- ### Problem Statement Given a N * N chessboards and N Queens Arrange the queens in a way that no queeen can attack the other queens. N rows => N Queens Example 1: Input : N = 1 | Q | | -------- | Input : N = 2 Output: Impossible Explanation: | Q | - | | -------- | -------- | | - | - | After Placing the first queen, here we cant able to place another queen, which makes it attack each other. --- title: N Queen Observation description: duration: 600 card_type: cue_card --- Process: * Place a Queen at a cell * Check whether the queen attacks any of the other queens. * If Yes, then dont place it * Else place the queen * If there is no arrangement of queen is possible, then prune it. ### Dry Run For N = 3 <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/366/original/upload_80f2a7100f72e76ecf3adfee95d39651.png?1711631164" width="500px"> As we can see that, for N = 3 also, there is no arrangement exist. Now, lets try with N = 4. <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/374/original/upload_13637cb457e68a47dc636b9f19ac59d1.png?1711632544" width="500px"> As we can see that, when we place the Queen on Column 1 on Row 0, there is a possiblity of placing 4 queens in the 4 x 4 matrix. ### Observation So now to check whether the queen attacks any other queen or not. It becomes a crutial part. If we check all the cells the queen can move, then it will consume more time. We will place one queen on each row, it may attack on one of the possible ways. <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/375/original/upload_2da9812fad1796aba22f098adcaf9129.png?1711632747" width="500px"> Now, lets focus on the Column move. For this, we can create a Hashset, and check whether there is any queen, which is already present or not. ```java HashSet<Int> cols ``` Lets focus on Difference Diagonal(top left - bottom right) <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/470/original/upload_d7bd9be48a6e441118d5e1509034ac0f.png?1711651528" width="500px"> Here we get the same value on each diagonal, when we substract col from row. ```java HashSet<Int> diffDiagonal ``` Now, Lets focus on the another diagonal (top right - bottom left) <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/471/original/57beca15-7a74-4c91-8ee7-26156a1c0fb1.jpg?1711651670" width="500px"> Here we can notice that, the sum of the row index and col index are same. ```java HashSet<Int> sumDiagonal ``` ### Pseudo Code ```java Hashset<int> cols N Hashset<int> different diagonal N Hashset<int> same diagonal N bool check (row, col) { if(cols. containskey(col)){ return False; } elseif(diffdiag.contains key(row - col)) { return False; } elseif(samediag.contains key(row + col)) { return False; } else { return True; } } ans [N][N] ={0} bool NQueen (row, N){ if (row == N){ print(ans); return True; } for(col=0; col < N ; col++ ){ if(check(row, col) == True){ ans[row][col] = 1; cols.insert(col); sumdiag.insert(row + col); diffdiag.insert(row - col); bool isValid = NQueen(row + 1, N); if(isValid){ return True; } else{ ans[row][col] = 0; cols.insert(col); sumdiag.insert(row + col); diffdiag.insert(row - col); } } } return False; } ``` ### Complexity **Time Complexity**: O(N!) **Space Complexity**: O(3N + N + N) = O(N2) = O(N) --- title: Problem 2 Suduko description: duration: 600 card_type: cue_card --- ### Sudoku You are given an 9x9 board, in which the cells contains numbers from 1 - 9. You need to check the below conditions, 1.Each row must contain the numbers from 1 to 9 w/o repititions. 2.Each col must contain the numbers from 1 to 9 w/o repititions. 3.Each block of size 3 * 3 should contain all numbers from 1 to 9 w/o repitition. <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/457/original/upload_2ea5e7ec30b3969557f5bcc767942458.png?1711650232" width="500px"> ### Observation For Each empty cell, we have 9 choices (1 - 9). After placing a number we need to check whether the particular number is present in the row, col or the belonging 3x3 square. <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/458/original/upload_2d58789b02a2d80893bd461ee1c3be75.png?1711650322" width="500px"> ### Pseudo Code ```java boolean sudoku (mat[][], i, j, g){ if(j == 9){ i = i+1; j = 0; } if(i == 9){ return True; } if(mat[i][j]! = 0){ if(sudoku(mat, i, j+1, 9)){ return True; } else{ return False; } } else{ for(x = 1; x <= 9; x++){ if(isValid(mat, i, j, x,g)){ mat[i][j] = x; { do if(sudoku(mat, i, j+1, 9)){ return True; } // undo mat[i][j] = 0; { } } } return False; } boolean isValid(mat, i, j, x, 9){ for(row = 0; row < 9; row++){ if(mat[row][j] == x){ return False; } } for(col = 0; col < 9; col++){ if(mat[i][col] == x){ return False; } } i = i - i % 3; j = j - j % 3; for(row = i; row < (i+3); row++){ for(col = j; col < (j+3); col++ ){ if(mat[row][col] == x){ return False; } } } return True; } ``` ### Complexity **Time Complexity**: (N$^2$ * N) **Space Complexity**: O(N$^2$) --- title: Problem 3 Word Break description: duration: 600 card_type: cue_card --- ### Problem Statement Given a dictionary of words(strings) (Hashset) and a string A Check if it is possible to break A into valid words from the dictionary. Dict = {'i', 'like', 'mango', 'man', 'go'} A = iamman A = ilikemango ### Dryrun Lets the string, i l i k e m a n g o Here, we need to create a recursive call, which makes the cuts. Lets start from the end, <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/459/original/upload_cc934933a1c7b8646a628fcefdd465d3.png?1711650384" width="500px"> Now lets try breaking on the last position <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/467/original/00bb17c5-a0ad-44c2-bfb3-a6695a494e47.jpg?1711650878" width ="500px"> Here "o" is not present in the dictionary, So we prune the call. Lets move ahead and try with another cut. <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/469/original/f9a984c0-3535-4cca-aae0-76db9bb6dbc0.jpg?1711650970" width = "500px"> As we can see that, "go" is present in our Dictionary. Then we have two choices, either we can move, or lets make it as a cut itself. Lets make it as a cut, then try making another cut Likewise, we can make the cut recusively <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/069/466/original/8e5049e7-47cf-4c6c-8508-985b4a57a10d.jpg?1711650796" width="400px"> Each recursive Function will return the number of cuts it made