代码随想录 第七章 回溯算法 part04 332.重新安排行程

332.重新安排行程

这题从理论的思路上并不难,但普通的回溯会超时,笔者一开始写了一个普通的回溯。

class Solution {
private:
    vector<vector<string>>result;
    vector<string>path;
    void bt(vector<vector<string>>& tickets){
        if(tickets.size()==0){
            result.push_back(path);
            return;
        }
        for(int i=0;i<tickets.size();i++){
            if(path.size()==0){
                if(tickets[i][0]=="JFK"){
                    path.push_back(tickets[i][0]);
                    path.push_back(tickets[i][1]);
                    vector<string>tmp=tickets[i];
                    tickets.erase(tickets.begin()+i);
                    bt(tickets);
                    tickets.insert(tickets.begin()+i,tmp);
                    path.pop_back();
                    path.pop_back();
                }
            }else{
                if(path[path.size()-1]!=tickets[i][0]) continue;
                path.push_back(tickets[i][1]);
                vector<string>tmp=tickets[i];
                tickets.erase(tickets.begin()+i);
                bt(tickets);
                tickets.insert(tickets.begin()+i,tmp);
                path.pop_back();
            }
        }
    }
public:
    vector<string> findItinerary(vector<vector<string>>& tickets) {
        bt(tickets);
        while(result.size()>1){
            for(int i=0;i<result[0].size();i++){
                if(result[0][i]==result[1][i]){
                    continue;
                }else if(result[0][i]>result[1][i]){
                    result.erase(result.begin());
                    break;
                }else if(result[0][i]<result[1][i]){
                    result.erase(result.begin()+1);
                    break;
                }
            }
        }
        return result[0];
    }
};

先通过普通的回溯求出所有可行路线,再对路线进行删除,直到剩下一条最小的,但是到第11个用例就超时了。笔者也尝试将删除路线的部分用于在回溯过程中剪枝,但依然超时,所以去看了随想录的解法,然后照着随想录的思路写。

class Solution {
private:
    unordered_map<string,map<string,int>>map;
    vector<string>path;
    int pathsize=0;
    bool bt(){
        if(path.size()==pathsize) return true;
        for(pair<const string,int>& i:map[path[path.size()-1]]){
            if(i.second==0) continue;
            i.second--;
            path.push_back(i.first);
            if(bt()) return true;
            i.second++;
            path.pop_back();
        }
        return false;
    }
public:
    vector<string> findItinerary(vector<vector<string>>& tickets) {
        map.clear();
        for(vector<string> i:tickets){
            map[i[0]][i[1]]++;
        }
        path.push_back("JFK");
        pathsize=tickets.size()+1;
        bt();
        return path;
    }
};

随想录的解法通过建立unordered_map,将从一个机场到其他机场的可能性都包含在unordered_map下的map,这样在回溯过程中不需要遍历tickets寻找合适的票,并且map基于黑红树实现,能够自动实现排序,因此通过map存储机场到其他机场的余票,遍历过程中天然就可以排除所有字典排序不是最小的路线,找到的第一条可行路线就是最小的。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值