Journey of LeetCode|DAY 26
Preface
This is a new day to continue my backtracking algorithm journey.
Learn something new and keep reviewing what I learnt before.
1. Reconstruct Itinerary
LeetCode Link: 332. Reconstruct Itinerary
You are given a list of airline tickets where tickets[i] = [fromi, toi] represent the departure and the arrival airports of one flight. Reconstruct the itinerary in order and return it.
All of the tickets belong to a man who departs from “JFK”, thus, the itinerary must begin with “JFK”. If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string.
For example, the itinerary [“JFK”, “LGA”] has a smaller lexical order than [“JFK”, “LGB”].
You may assume all tickets form at least one valid itinerary. You must use all the tickets once and only once.
Analysis and Solution
BackTrack
LeetCode C++ as followings BackTrack
class Solution {
private:
// unordered_map<departure airport, map<arrival airport, number of flights>> targets
unordered_map<string, map<string, int>> targets;
bool backtracking(int ticketNum, vector<string>& result) {
if (result.size() == ticketNum + 1) {//terminate condition
return true;
}
for (pair<const string, int>& target : targets[result[result.size() - 1]]) {
if (target.second > 0 ) { // Record whether the arrival airport has been flown
result.push_back(target.first);
target.second--;
if (backtracking(ticketNum, result)) return true;
result.pop_back();
target.second++;
}
}
return false;
}
public:
vector<string> findItinerary(vector<vector<string>>& tickets) {
targets.clear();
vector<string> result;
for (const vector<string>& vec : tickets) {
targets[vec[0]][vec[1]]++; // Record mapping relationship
}
result.push_back("JFK"); // origin airport
backtracking(tickets.size(), result);
return result;
}
};
2. N-Queens
LeetCode Link: 51. N-Queens
The n-queens puzzle is the problem of placing n queens on an n x n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle. You may return the answer in any order.
Each solution contains a distinct board configuration of the n-queens’ placement, where ‘Q’ and ‘.’ both indicate a queen and an empty space, respectively.
Analysis and Solution
BackTrack
LeetCode C++ as followings BackTrack
class Solution {
private:
vector<vector<string>> result;
// n is the size of chessboard that input from outside
// row is recursive to the nth line of the chessboard
void backtracking(int n, int row, vector<string>& chessboard) {
if (row == n) {//terminate condition
result.push_back(chessboard);
return;
}
for (int col = 0; col < n; col++) {
if (isValid(row, col, chessboard, n)) { // put queen if it is valid
chessboard[row][col] = 'Q'; // place queen
backtracking(n, row + 1, chessboard);
chessboard[row][col] = '.'; // backtrack,undo queen
}
}
}
bool isValid(int row, int col, vector<string>& chessboard, int n) {
// check column
for (int i = 0; i < row; i++) {
if (chessboard[i][col] == 'Q') {
return false;
}
}
// Check if there is a queen at a 45 degree angle
for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
// Check if there is a queen at a 135 degree angle
for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
return true;
}
public:
vector<vector<string>> solveNQueens(int n) {
result.clear();
std::vector<std::string> chessboard(n, std::string(n, '.'));
backtracking(n, 0, chessboard);
return result;
}
};
3. Sudoku Solver
LeetCode Link: 37. Sudoku Solver
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
Each of the digits 1-9 must occur exactly once in each row.
Each of the digits 1-9 must occur exactly once in each column.
Each of the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.
The ‘.’ character indicates empty cells.
Analysis and Solution
BackTrack
LeetCode C++ as followings BackTrack
class Solution {
private:
bool backtracking(vector<vector<char>>& board) {
for (int i = 0; i < board.size(); i++) { // iterate over rows
for (int j = 0; j < board[0].size(); j++) { // iterate over columns
if (board[i][j] == '.') {
for (char k = '1'; k <= '9'; k++) { // (i, j) judge if it is appropriate to put k in this position
if (isValid(i, j, k, board)) {
board[i][j] = k; // place k
if (backtracking(board)) return true; // Return immediately if a suitable set is found
board[i][j] = '.'; // backtrack,undo k
}
}
return false; // After all 9 numbers have been tried, if none work, then return false
}
}
}
return true; // False is not returned after traversing, indicating that a suitable chessboard position has been found
}
bool isValid(int row, int col, char val, vector<vector<char>>& board) {
for (int i = 0; i < 9; i++) { // Determine whether the row is repeated
if (board[row][i] == val) {
return false;
}
}
for (int j = 0; j < 9; j++) { // Determine whether the column is repeated
if (board[j][col] == val) {
return false;
}
}
int startRow = (row / 3) * 3;
int startCol = (col / 3) * 3;
for (int i = startRow; i < startRow + 3; i++) { // Determine whether 9 squares are repeated
for (int j = startCol; j < startCol + 3; j++) {
if (board[i][j] == val ) {
return false;
}
}
}
return true;
}
public:
void solveSudoku(vector<vector<char>>& board) {
backtracking(board);
}
};