Marathon Ranking

题目描述:https://www.1point3acres.com/bbs/thread-225621-1-1.html

这道题是Bloomberg经典面试题,和LRU非常类似。维护一个list记录runner的顺序,一旦有runner经过sensor,我们就需要调整位置。本质其实就是要写一个 update(runner i, sensor j) 的函数。

注意C++中 list.splice 函数,由于对同一个list进行操作,指针不会失效,仍指向原来的list元素,runner2pos 也不用更新。

// https://www.1point3acres.com/bbs/thread-225621-1-1.html

class Marathon{
    int m, n; // m runner with id 1-m, n sensor with id 1-n
    list<int> l; // record order of all runners
    vector<list<int>::iterator> runner2pos; // runner_id -> the pos in list
    vector<int> passedSensor; // runner_id -> record how many sensors have been passed
    vector<int> firstPassed; // sensor_id -> the first runner who passed the sensor

public:
    Marathon(int _m, int _n){
        m = _m;
        n = _n;
        runner2pos.resize(m+1);
        passedSensor.resize(m+1,0);
        firstPassed.resize(n+1,0);
        firstPassed[0] = 1; // at first in the order of 1~m
        for (int i=1;i<=m;++i) l.push_back(i);
        for (auto it=l.begin();it!=l.end();++it){
            runner2pos[distance(l.begin(),it)+1]=it;
            // cout << distance(l.begin(),it)+1 << ' ' << *it << endl;
        }
    }
        
    void passMilestone(int runner_id){
        int sensor_id = ++passedSensor[runner_id];
        if (firstPassed[sensor_id]==0) firstPassed[sensor_id]=runner_id;
        // runner_id passed sensor_id, insert this runner to the front of previous sensor
        auto cur_pos=runner2pos[runner_id];
        auto new_pos=runner2pos[firstPassed[sensor_id-1]];
        l.splice(new_pos,l,cur_pos);
    }
            
    void printLeadBoard(){
        for (auto x:l) cout<<x<<' ';
        cout << endl;
    }
};

int main() {
    Marathon m(3,2);
    m.passMilestone(3); // runner 3 passed sensor 1
    m.printLeadBoard();
    m.passMilestone(2); // runner 2 passed sensor 1
    m.printLeadBoard();
    m.passMilestone(2); // runner 2 passed sensor 2
    m.printLeadBoard();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hankunyan/p/11566707.html