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;
    }
};
相关推荐
浅念-4 小时前
递归解题指南:LeetCode经典题全解析
数据结构·算法·leetcode·职场和发展·排序算法·深度优先·递归
Kiling_07044 小时前
Java集合进阶:Set与Collections详解
算法·哈希算法
智者知已应修善业5 小时前
【51单片机89C51及74LS273、74LS244组成】2022-5-28
c++·经验分享·笔记·算法·51单片机
洛水水5 小时前
【力扣100题】33.验证二叉搜索树
算法·leetcode·职场和发展
SimpleLearingAI5 小时前
聚类算法详解
算法·数据挖掘·聚类
刀法如飞6 小时前
Go 字符串查找的 20 种实现方式,用不同思路解决问题
算法·面试·程序员
Dlrb12118 小时前
C语言-指针数组与数组指针
c语言·数据结构·算法·指针·数组指针·指针数组·二级指针
WL_Aurora8 小时前
Python 算法基础篇之集合
python·算法
平行侠8 小时前
A15 工业路由器IP前缀高速检索与内存压缩系统
网络·tcp/ip·算法
阿旭超级学得完9 小时前
C++11包装器(function和bind)
java·开发语言·c++·算法·哈希算法·散列表