代码随想录算法训练营 Day30 | LeetCode332.重新安排行程、LeetCode51. N皇后、LeetCode37. 解数独、回溯算法总结

LeetCode332.重新安排行程

本题较为困难,难点在于选取怎样的容器来表示不同地点的映射关系,并且一个地点是可以反复经过的,这个逻辑怎样映射到回溯的思想中,这里面map<string,int>里的int存放的即为航班还需要航行到这里的次数。

本题较难,没有太深究,贴卡哥代码如下:

class Solution {
private:
    // unordered_map<出发机场, map<到达机场, 航班次数>> targets
    unordered_map<string, map<string, int>> targets;
    bool backtracking(int ticketNum, vector<string>& result) {
        if (result.size() == ticketNum + 1) {
            return true;
        }
        for (pair<const string, int>& target : targets[result[result.size() - 1]]) {
            if (target.second > 0 ) { // 记录到达机场是否飞过了
                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]]++; // 记录映射关系
        }
        result.push_back("JFK"); // 起始机场
        backtracking(tickets.size(), result);
        return result;
    }
};

LeetCode51. N皇后

感觉逻辑上和组合问题是一样的,对于组合问题,就是利用递归代替了层数的for循环,那么在N皇后问题中,就是用递归代替行数的for循环,这里面行数就是树的深度。

判断是否合法的函数中,只需要判断可能下过棋的位置即可,包括左上、上、右上三部分。

class Solution {
public:
    vector<vector<string>> result;
    void backtracking(int n,int row,vector<string>& chessboard){
        if(row==n){
            result.push_back(chessboard);
            return;
        }
        for(int i=0;i<n;i++){
            if(isValid(row,i,chessboard,n)){ //判断位置合法后再下棋
                chessboard[row][i] = 'Q';
                backtracking(n,row+1,chessboard);
                chessboard[row][i] = '.';
            }
        }
        return;
    }
    bool isValid(int row,int col,vector<string>& chessboard,int n){
        for(int i=0;i<row;i++){
            if(chessboard[i][col]=='Q') return false;
        }
        for(int i=row-1,j=col-1;i>=0&&j>=0;i--,j--){
            if(chessboard[i][j]=='Q') return false;
        }
        for(int i=row-1,j=col+1;i>=0&&j<=n;i--,j++){
            if(chessboard[i][j]=='Q') return false;
        }
        return true;
    }
    vector<vector<string>> solveNQueens(int n) {
        vector<string> chessboard(n,string(n,'.'));
        backtracking(n,0,chessboard);
        return result;
    }
};

LeetCode37. 解数独

在N皇后问题中,只需要在一行中确定一个皇后的位置即可,因此是一个一维递归问题。而在熟读问题中,需要确定一行中每个空格的数字,因此是一个二维递归的问题。

因此题目只要求返回一个符合条件的结果,所以返回值为bool,遇到结果就返回

在回溯函数中,注意几层for循环结束的返回值是true还是false;

class Solution {
public:
    bool backtracking(vector<vector<char>>& board){
        for(int i=0;i<board.size();i++){
            for(int j=0;j<board[0].size();j++){
                if(board[i][j]=='.'){
                    for(char k='1';k<='9';k++){
                        if(isValid(i,j,k,board)){
                            board[i][j] = k;
                            bool result = backtracking(board);
                            if(result) return true;
                            board[i][j] = '.';
                        }
                    }
                    return false; //1-9都没有合适的数字,直接false
                }
            }
        }
        return true; //都没有遇到false,说明将所有的空格都更新了,返回true;
    }
    bool isValid(int row,int col,char num,vector<vector<char>>& board){
        for(int i=0;i<9;i++){
            if(board[i][col]==num) return false;
        }
        for(int j=0;j<9;j++){
            if(board[row][j]==num) return false;
        }
        int startRow = (row / 3) * 3;
        int startCol = (col / 3) * 3;
        for (int i = startRow; i < startRow + 3; i++) { // 判断9方格里是否重复
            for (int j = startCol; j < startCol + 3; j++) {
                if (board[i][j] == num ) return false;
            }
        }
        return true;
    }
    void solveSudoku(vector<vector<char>>& board) {
        backtracking(board);
        return;
    }
};

回溯算法总结

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值