面试18之猫狗队列
2017-04-27 19:06
183 查看
题目描述
有家动物收容所只收留猫和狗,但有特殊的收养规则,收养人有两种收养方式,第一种为直接收养所有动物中最早进入收容所的,第二种为选择收养的动物类型(猫或狗),并收养该种动物中最早进入收容所的。
给定一个操作序列int[][2] ope(C++中为vector<vector<int>>)代表所有事件。若第一个元素为1,则代表有动物进入收容所,第二个元素为动物的编号,正数代表狗,负数代表猫;若第一个元素为2,则代表有人收养动物,第二个元素若为0,则采取第一种收养方式,若为1,则指定收养狗,若为-1则指定收养猫。请按顺序返回收养的序列。若出现不合法的操作,即没有可以符合领养要求的动物,则将这次领养操作忽略。
测试样例:
[[1,1],[1,-1],[2,0],[2,-1]]
返回:[1,-1]
方法一:
用一个vector来表示收养所,数组的头部元素就是最早进入收留所的动物,遍历一遍,找到第一个大于0的编号就是狗,第一个小于0的编号就是猫,
这种方式简单,但是效率低,每出一个动物都得遍历一遍,时间复杂度为O(N*N)。
方式二:
因为先进先出,用两个队列来表示收养所,猫队列的头部就是最早进入收留所的猫,狗队列的头部就是最早进入收留所的狗,
但是这种形式我们不能确定第一个进入的猫和第一个进入的狗谁最早进入,所以我们想到当入队列的时候,把动物的时间也压入。用一个额外的int变量来表示时序。
测试代码:
有家动物收容所只收留猫和狗,但有特殊的收养规则,收养人有两种收养方式,第一种为直接收养所有动物中最早进入收容所的,第二种为选择收养的动物类型(猫或狗),并收养该种动物中最早进入收容所的。
给定一个操作序列int[][2] ope(C++中为vector<vector<int>>)代表所有事件。若第一个元素为1,则代表有动物进入收容所,第二个元素为动物的编号,正数代表狗,负数代表猫;若第一个元素为2,则代表有人收养动物,第二个元素若为0,则采取第一种收养方式,若为1,则指定收养狗,若为-1则指定收养猫。请按顺序返回收养的序列。若出现不合法的操作,即没有可以符合领养要求的动物,则将这次领养操作忽略。
测试样例:
[[1,1],[1,-1],[2,0],[2,-1]]
返回:[1,-1]
方法一:
用一个vector来表示收养所,数组的头部元素就是最早进入收留所的动物,遍历一遍,找到第一个大于0的编号就是狗,第一个小于0的编号就是猫,
这种方式简单,但是效率低,每出一个动物都得遍历一遍,时间复杂度为O(N*N)。
vector<int> Asylum(vector<vector<int> > ope) { vector<int> A; //表示收养所 vector<int> B; //表示被收养的动物。 for(int i = 0; i < ope.size(); ++i) { if(ope[i][0] == 1) //表示动物进收留所。 { A.push_back(ope[i][1]); //将动物的编号放入收养所。 } if(ope[i][0] == 2) //表示有人收养动物了。 { if(A.empty()) //如果收养所没有动物能收养,自己结束这次操作。 continue; if(ope[i][1] == 0) //第一种方式收养。收养的是最早进入收留所的动物。 { B.push_back(A[0]); //收留所 要清除最早的动物。 A.erase(A.begin()); } if(ope[i][1] == 1) //收养最早的狗。狗的编号大于0 { for(int j = 0; j < A.size(); ++j) { if(A[j] > 0) //找到最早的狗 { B.push_back(A[j]); A.erase(A.begin()+j); break; } } } if(ope[i][1] == -1) //收养最早的猫。 { for(int j = 0; j < A.size(); ++j) { if(A[j] < 0) //找到最早的猫,猫的编号小于0. { B.push_back(A[j]); A.erase(A.begin()+j); break; } } } } } return B; }
方式二:
因为先进先出,用两个队列来表示收养所,猫队列的头部就是最早进入收留所的猫,狗队列的头部就是最早进入收留所的狗,
但是这种形式我们不能确定第一个进入的猫和第一个进入的狗谁最早进入,所以我们想到当入队列的时候,把动物的时间也压入。用一个额外的int变量来表示时序。
vector<int> Asylum(vector<vector<int> > ope) { queue<int> cat; queue<int> dog; vector<int> ret; int idx = 0; //表示时间。 for(int i = 0; i < ope.size(); ++i) { if(ope[i][0] == 1) //有动物要进收养所了。 { if(ope[i][1] > 0) //编号大于0,表示狗进入 { dog.push(idx++); //把动物的时序也一并压入。 dog.push(ope[i][1]); } else { cat.push(idx++); cat.push(ope[i][1]); } } if(ope[i][0] == 2) //表示有人要收养动物了。 { if(ope[i][1] == 0) //第一种方式收养,收养最早的动物。 { int catidx = cat.empty() ? 10000000 :cat.front(); int dogidx = dog.empty() ? 10000000 :dog.front(); if(catidx < dogidx) { cat.pop(); //把时序弹出。 ret.push_back(cat.front() ); cat.pop(); } else { dog.pop(); //把时序弹出。 ret.push_back(dog.front() ); dog.pop(); } } else if(ope[i][1] == 1) //第二种方式收养,收养狗 { if(!dog.empty()) { dog.pop(); //把时序弹出。 ret.push_back(dog.front() ); dog.pop(); } } else { if(!cat.empty() ) { cat.pop(); //把时序弹出。 ret.push_back(cat.front() ); cat.pop(); } } } } return ret; }
测试代码:
void test() { vector<int > v[4]; v[0].push_back(1); v[0].push_back(1); v[1].push_back(1); v[1].push_back(-1); v[2].push_back(2); v[2].push_back(0); v[3].push_back(2); v[3].push_back(-1); vector<vector<int> > vv; for(int i = 0; i < 4; ++i) { vv.push_back(v[i]); } vector<int> ret = Asylum(vv); for(int i = 0; i < ret.size(); ++i) { cout << ret[i] << " "; } cout <<endl; } int main() { test(); cout << "hello..."<<endl; return 0; }
相关文章推荐
- 网络工程师面试答案(8和18、19)
- 程序员面试题精选(18):用两个栈实现队列
- 点评互联网产品经理面试问题汇总(18问)
- 并发编程 18—— 使用内置条件队列实现简单的有界缓存
- 螺旋队列(螺旋矩阵)——创新工场面试总结2
- 程序员面试题精选100题(18)-用两个栈实现队列
- 微软面试100题之18题:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始... ...
- 实现一个队列 【微软面试100题 第三十四题】
- Java面试18|关于进程、线程与协程
- 【C/C++学院】0730-网站以及后门/结构体对齐、结构体面试分析/深拷贝与浅拷贝/队列/字符串封装
- PTA-数据结构 5-18 银行业务队列简单模拟 (25分)
- CSDN社区分享面试经历活动作品18——话说我的面试经历
- 【Android面试】Android面试题集锦 (陆续更新)(最新2012-6-18)
- 队列---面试知识点整理
- 面试---两个队列实现一个栈
- [Python面试知识]数据结构之栈和队列实现
- 面试之路(18)-java的函数参数传递类型之值传递还是引用传递
- 求职者18则面试的禁口话题
- 面试 16:栈的压入压出队列(剑指 Offer 第 22 题)
- 面试18问