day-30 代码随想录算法训练营 回溯part06

332.重新安排行程

思路:使用unordered_map记录起点机场对应到达机场,内部使用map记录到达机场的次数(因为map会进行排序,可以求出最小路径)
cpp 复制代码
class Solution {
public:
    vector<string>res;
    unordered_map<string,map<string,int>>targets;//使用map主要是map会自动根据键值自动排序
    bool backtrace(vector<vector<string>>&tickets){
        if(res.size()==tickets.size()+1)
            return true;
        for(pair<const string,int>&target:targets[res[res.size()-1]]){
            if(target.second>0){
                res.push_back(target.first);
                target.second--;
                if(backtrace(tickets)==true) return true;
                target.second++;
                res.pop_back();
            }
        }
        return false;
    }
    vector<string> findItinerary(vector<vector<string>>& tickets) {
        res.push_back("JFK");//插入起点
        //记录每个机场出发到达情况
        for(auto it:tickets)
            targets[it[0]][it[1]]++;//根据起点机场,找到到达机场,并记录到达机场的次数
        backtrace(tickets);
        return res;

    }
};

51.N皇后

思路:递归遍历棋盘的每一行,然后在每一行中寻找有效位置,找到时才进行下一次递归遍历
有效位置的判断:
判断左斜线上方
判断右斜线上方
判断上方同一列
cpp 复制代码
class Solution {
public:
    vector<vector<string>>res;
    bool judge(int row,int colum,vector<string>&mids,int n){
        //判断行(行上无需判断,因为每一个都是一种回溯
        //判断列
        for(int i=0;i<row;i++){
            if(mids[i][colum]=='Q')
                return false;
        }

        //判断左上方
        for(int i=row-1,j=colum-1;i>=0 && j>=0;i--,j--){
            if(mids[i][j]=='Q')
                return false;
        }

        //判断右上方
        for(int i=row-1,j=colum+1;i>=0 && j<n;i--,j++){
            if(mids[i][j]=='Q')
                return false;
        }
        return true;
    }
    void backtrace(vector<string>&mids,int start,int n){
        if(start==n){//整个棋盘每一行都遍历摆完
            res.push_back(mids);
            return;
        }
        for(int i=0;i<n;i++){
            if(judge(start,i,mids,n)){//判断该位置是否有效
                mids[start][i]='Q';
                backtrace(mids,start+1,n);
                mids[start][i]='.';
            }
        }
    }
    vector<vector<string>> solveNQueens(int n) {
        vector<string>mids(n,string(n,'.'));
        backtrace(mids,0,n);
        return res;
    }
};

37.解数独

思路:遍历整个数独棋盘
然后从1-9依次判断是否能放入当前位置,当能放入时,放置当前值,然后递归开启下一次遍历,同时判断下一次遍历是否true,
在填入该值后,数独能填完的情况下,最后都会返回true
  • 在填入该值后,后序数独无法填完,就返回false

在遍历完1-9还无法有效放入,则直接返回false

cpp 复制代码
class Solution {
public:
    bool isvaild(int row,int colum,char val,vector<vector<char>>&board){
        //判断这一行
        for(int i=0;i<9;i++){
            if(board[row][i]==val) return false;
        }
        //判断这一列
        for(int j=0;j<9;j++){
            if(board[j][colum]==val) return false;
        }
        //判断九宫格
        int midRow=(row/3)*3;//比如0、1、2都被限制为0*3,后面3,4,5限制为1*3
        int midColum=(colum/3)*3;
        for(int i=midRow;i<midRow+3;i++){
            for(int j=midColum;j<midColum+3;j++){
                if(board[i][j]==val)
                    return false;
            }
        }
        return true;
    }
    bool backtrace(vector<vector<char>>&board){
        for(int i=0;i<board.size();i++){
            for(int j=0;j<board[i].size();j++){
                if(board[i][j]=='.'){
                    for(char k='1';k<='9';k++){
                        if(isvaild(i,j,k,board)){
                            board[i][j]=k;
                            if(backtrace(board))//该位置k有效时,进入递归判断
                                return true;
                            board[i][j]='.';//无效时,直接回溯
                        }       
                    }
                    return false;//所有数字都无效情况下,直接返回false
                }
            }
        }
        return true;
    }
    void solveSudoku(vector<vector<char>>& board) {
        backtrace(board);
    }
};

53.最大子数组和

思路:遍历数组,计算连续和,当连续和持续增大时更新最大连续和;当连续和为负值时,重置连续和为0,下一次重新计算连续和
cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n=nums.size();
        int count=0,result=INT_MIN;
        for(int i=0;i<n;i++){
            count+=nums[i];
            if(count>result)//更新最大和
                result=count;
            if(count<=0) count=0;//因为要求连续子数组,出现和为负的情况直接更新和为0,
                                 //从下一位开始计算
        }
        return result;
    }
};

122.买卖股票的最佳时机||

思路:不需要考虑哪一天买入卖出,只需要找出每相邻两个数的递增值,在大于0的情况下累加,这样就都能收获利润
cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        int res=0;
        for(int i=1;i<n;i++){
            if(prices[i]>prices[i-1])//当可以产生利润时
                res+=(prices[i]-prices[i-1]);//累加利润
        }
        return res;
    }
};

55.跳跃游戏

思路一:从第一个位置开始更新最大覆盖值,然后在最大覆盖值的范围中寻找是否有到达目标位置的情况
cpp 复制代码
class Solution {
public:
    bool canJump(vector<int>& nums) {
        int cover=0;
        if(nums.size()==1) return true;
        for(int i=0;i<=cover;i++){//在最大覆盖值中寻找
            cover=max(i+nums[i],cover);//更新最大覆盖值
            if(cover>=nums.size()-1) return true;//出现覆盖值可以到达终点
        }
        return false;
    }
};
相关推荐
向宇it22 分钟前
【unity小技巧】Unity 四叉树算法实现空间分割、物体存储并进行查询和碰撞检测
开发语言·算法·游戏·unity·游戏引擎
无限大.22 分钟前
冒泡排序(结合动画进行可视化分析)
算法·排序算法
走向自由42 分钟前
Leetcode 最长回文子串
数据结构·算法·leetcode·回文·最长回文
nuo5342021 小时前
The 2024 ICPC Kunming Invitational Contest
c语言·数据结构·c++·算法
luckilyil1 小时前
Leetcode 每日一题 11. 盛最多水的容器
算法·leetcode
A.A呐1 小时前
LeetCode 1658.将x减到0的最小操作数
算法·leetcode
hn小菜鸡1 小时前
LeetCode 144.二叉树的前序遍历
算法·leetcode·职场和发展
rubyw2 小时前
如何选择聚类算法、回归算法、分类算法?
算法·机器学习·分类·数据挖掘·回归·聚类
编程探索者小陈2 小时前
【优先算法】专题——双指针
数据结构·算法·leetcode
夫琅禾费米线2 小时前
leetcode2650. 设计可取消函数 generator和Promise
开发语言·javascript·leetcode·ecmascript