仅当集合为空时才会弹出值

时间:2018-02-20 00:28:36

标签: c++ algorithm graph graph-traversal

我正在解决关于Leetcode的问题:https://leetcode.com/problems/reconstruct-itinerary/description/。问题是:

Given a list of airline tickets represented by pairs of departure and 
arrival airports [from, to], reconstruct the itinerary in order. All of 
the tickets belong to a man who departs from JFK. Thus, the itinerary 
must begin with JFK.

例如,如果tickets = [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]],则输出应为:["JFK", "MUC", "LHR", "SFO", "SJC"]

我编写了以下代码,其中(可以理解)中断输入[["JFK","KUL"],["JFK","NRT"],["NRT","JFK"]],因为根据我的代码,节点" NRT"仍未被访问:

class Solution {
public:
    vector<string> findItinerary(vector<pair<string, string>> tickets) {
        if(tickets.empty()) return vector<string>();

        vector<string> result;
        unordered_map<string, multiset<string>> itinerary;

        for(auto& each : tickets)
            itinerary[each.first].insert(each.second);

        stack<string> myStack;
        myStack.push("JFK");
        while(!myStack.empty()) {
            string topVal=myStack.top();
            result.push_back(topVal);
            myStack.pop();
            if(!itinerary[topVal].empty()) {
                myStack.push(*itinerary[topVal].begin());
                itinerary[topVal].erase(itinerary[topVal].begin());
            }
        }

        return result;
    }
};

为了克服这个问题,其中一个受欢迎的解决方案提出了这一小改变:

class Solution {
public:
    vector<string> findItinerary(vector<pair<string, string>> tickets) {
        if(tickets.empty()) return vector<string>();

        vector<string> result;
        unordered_map<string, multiset<string>> itinerary;

        for(auto& each : tickets)
            itinerary[each.first].insert(each.second);

        stack<string> myStack;
        myStack.push("JFK");
        while(!myStack.empty()) {
            string topVal=myStack.top();
            if(itinerary[topVal].empty()) {   //--->this if condition
                result.push_back(topVal);
                myStack.pop();
            }
            else {
                myStack.push(*itinerary[topVal].begin());
                itinerary[topVal].erase(itinerary[topVal].begin());
            }
        }

        reverse(result.begin(), result.end());
        return result;
    }
};

现在,我使用示例[["JFK","KUL"],["JFK","NRT"],["NRT","JFK"]]处理了此代码,并了解了它如何以相反的方式将值插入result向量;但我不理解if条件背后的直觉

仅当设置为空时如何从堆栈弹出,确保此测试用例得到处理?

2 个答案:

答案 0 :(得分:0)

访问to城市后,系统会将其删除,这实际上意味着to城市作为中间from城市已被访问,下次相应from时无需考虑1}}城市被访问,否则它将是一个永无止境的循环,没有停止条件。

因此,if语句是检查发生的位置,to城市的所有from城市是否已经访问过。它几乎就像一个访问过的阵列,跟踪到目前为止所访问的所有城市。

答案 1 :(得分:0)

问题主要是在有向图中找到Eulerian path,其中每个[from,to]对代表一条边。

upvoted答案使用了一种名为Hierholzer's algorithm的算法(Hierholzer算法最初用于查找欧拉循环,但它很容易为欧拉修改它<强>路径)。一般来说,它

  

继续使用未使用的边缘并移除它们直到我们卡住。 一旦卡住,我们会回溯到当前路径中具有未使用边缘的最近顶点,然后重复此过程直到所有边缘都被使用。

强调的部分是您的解决方案与支持的解决方案之间的区别。

P.S。虽然算法很简单,但正确性的证明并不是那么简单。如果您对它感兴趣,可以在互联网上搜索。