文章目录
1. Dota2参议院
思路:就是一大帮不同阵营的人,按顺序投票,一轮一轮接下去,笑到最后的就是赢家。
1、 必须保证他们每一轮的位置是相对固定的
2、在各轮投票中,不断地淘汰对方阵营的人,淘汰地策略是什么呢? 先得到投票权的人,必定要淘汰离自己最近的敌方阵营的人,很容易想到这个贪心策略。
3、 那如何在淘汰,投票后进入下一轮保持这个位置呢? 仔细想想,这个过程很像排队,一个人投完就得等下一轮,相当于又去到末尾。
4、那类似排队模拟,必须是使用队列了
5、 第一反应必须是设计一个队列,让他们轮流排队, 但是,可以预见,这个队列不能很好满足我们的要求: 假设队列:RRRDD , 第一个R,必然想将第一个D淘汰出去(出队),这可得让一个中间的元素出队呀!
6、队列是最贴近的数据结构了,这时候,可能需要一些经验,或者有意识地思考,一个不行,那就两个。
7、两个队列,代表着什么?队列代表两方阵营的人。 保存的是什么数据? 我们需要知道两个队列的人的相对位置,那么队列里应该保存的,是两方阵营的站位顺序
8、接下来,每个人都需要禁言下一个离自己最近的敌人,如果单靠队列先进先出的性质,是不行的,“DRRD” ,对于第二个R,他应该删除自己后面的D,而不是队列头(第一个D)
9、编码设计: 将两个队列头的人拿出来PK,PK完后将存活的人放到队列最后面,保证他下一轮才上场
class Solution
{
private :
const string r = "Radiant", d = "Dire";
queue<int> radiant,dire;
public:
string predictPartyVictory(string senate)
{
int size = senate.size() ;
for(int i=0;i<size;i++){
if(senate[i]=='R')
radiant.push(i) ;
else dire.push(i) ;
}
while(!radiant.empty()&&!dire.empty()){
int r1=radiant.front (),d1=dire.front() ;
if(r1<d1) {
radiant.push(r1+size) ;
}else{
dire.push(d1 + size); // 思考一下为什么一定要加固定值size?
}
radiant.pop();
dire.pop();
}
if(radiant.empty()) return d ;
return r ;
}
};
总结:
算法和数据结构相辅相成 。
写算法题不仅仅是设计算法,还要设计数据结构。不仅要思考用那种数据结构,更要思考数据结构保存的是什么数据。
有时候算法再好,没有匹配的数据结构,还是事倍功半。
就拿这题来说,我一开始就只想着用一个队列,但与之匹配的算法需要这个队列支持从中间删除元素,必然不符合队列的设计思想。