http://blog.csdn.net/tianshuai1111/article/details/7490902
一,题目:(谷歌笔试)
n支队伍比赛,分别编号为0,1,2……n-1,已知它们之间的实力对比关系,存储在一个二维数组w[n][n]中,w[i][j] 的值代表编号为i,j的队伍中更强的一支。所以w[i][j]=i 或者j,现在给出它们的出场顺序,并存储在数组order[n]中,比如order[n] = {4,3,5,8,1......},那么第一轮比赛就是 4对3, 5对8。.......胜者晋级,败者淘汰,同一轮淘汰的所有队伍排名不再细分,即可以随便排,下一轮由上一轮的胜者按照顺序,再依次两两比,比如可能是4对5,直至出现第一名
编程实现,给出二维数组w,一维数组order 和 用于输出比赛名次的数组result[n],求出result(特别注意:result输出的是从第一名到最后一名)
二,分析
这里有一个简单的做法,就是:查看每一行重复数字个数,如果重复数字个数为n则排名为1,重复数字个数n-1则排名为2。所以重复数字个数为i个,则排名为n+1-i;给出order[],则相应的result很容易得出。这里值得注意的是:order仅仅为出场顺序,跟result没有任何关系。
对应源码为:
- #include <iostream>
- #include <stack>
- using namespace std;
- /*order 顺序为pk顺序*/
- int main()
- {
- int w[6][6] = { //排名 重复数
- 0,1,2,3,0,0, //4 3
- 1,1,2,1,1,1, //2 5
- 2,2,2,2,2,2, //1 6
- 3,1,2,3,3,3, //3 4
- 0,1,2,3,4,5, //6 1
- 0,1,2,3,5,5 //5 2
- };
- int order[6] = {1,3,4,2,0,5};
- int weight[6];//2,3,6,1,4,5
- int result[6];
- int max;
- for(int i=0;i<6;i++)
- {
- max=0;
- int temp[6]={0,0,0,0,0,0};
- for(int j=0;j<6;j++)
- {
- temp[w[i][j]]++;
- }
- for(int k=0;k<6;k++)//获取排名
- {
- if(max<temp[k])
- max=temp[k];//获取最大重复数
- }
- weight[i]=7-max;//排名
- }
- int n=6;
- int count=6;
- int count_left=0;
- int flag;
- while(count)
- {
- count_left=0;
- for(int i=0;i<6;i=i+2)
- {
- if(weight[order[i]]>weight[order[i+1]])
- {
- result[--count]=order[i];//排名在后面的直接
- order[count_left++]=order[i+1];//排名在前面的
- }
- else
- {
- result[--count]=order[i+1];
- order[count_left++]=order[i];
- }
- if(i!=0)
- {
- order[count_left++]=order[i+1];
- }
- if(count==0)
- result[0]=order[0];
- }
- // cout<<"count "<<count<<endl;
- }
- //result[0]=weight[order[i]];
- for(int i=0;i<6;i++)
- {
- cout<<result[i]<<endl;
- }
- return 0;
- }
#include <iostream>
#include <stack>
using namespace std;
/*order 顺序为pk顺序*/
int main()
{
int w[6][6] = { //排名 重复数
0,1,2,3,0,0, //4 3
1,1,2,1,1,1, //2 5
2,2,2,2,2,2, //1 6
3,1,2,3,3,3, //3 4
0,1,2,3,4,5, //6 1
0,1,2,3,5,5 //5 2
};
int order[6] = {1,3,4,2,0,5};
int weight[6];//2,3,6,1,4,5
int result[6];
int max;
for(int i=0;i<6;i++)
{
max=0;
int temp[6]={0,0,0,0,0,0};
for(int j=0;j<6;j++)
{
temp[w[i][j]]++;
}
for(int k=0;k<6;k++)//获取排名
{
if(max<temp[k])
max=temp[k];//获取最大重复数
}
weight[i]=7-max;//排名
}
int n=6;
int count=6;
int count_left=0;
int flag;
while(count)
{
count_left=0;
for(int i=0;i<6;i=i+2)
{
if(weight[order[i]]>weight[order[i+1]])
{
result[--count]=order[i];//排名在后面的直接
order[count_left++]=order[i+1];//排名在前面的
}
else
{
result[--count]=order[i+1];
order[count_left++]=order[i];
}
if(i!=0)
{
order[count_left++]=order[i+1];
}
if(count==0)
result[0]=order[0];
}
// cout<<"count "<<count<<endl;
}
//result[0]=weight[order[i]];
for(int i=0;i<6;i++)
{
cout<<result[i]<<endl;
}
return 0;
}
上述源码中,明显的缺点就是,通过记录重复个数来判断哪个优先级高。这里完全可以根据两个元素行与列交叉处值来判断。
改进后源码:
- #include <iostream>
- #include <stack>
- using namespace std;
- /*order 顺序为pk顺序*/
- int main()
- {
- int w[6][6] = { //排名 重复数
- 0,1,2,3,0,0, //4 3
- 1,1,2,1,1,1, //2 5
- 2,2,2,2,2,2, //1 6
- 3,1,2,3,3,3, //3 4
- 0,1,2,3,4,5, //6 1
- 0,1,2,3,5,5 //5 2
- };
- int order[6] = {1,3,4,2,0,5};
- int result[6];
- int count=6;
- int count_left=0;
- int flag;
- while(count)
- {
- count_left=0;
- for(int i=0;i<6;i=i+2)
- {
- int nWiner = *((int*)w + 6 * order[i] + order[i+1]);//取两个数交叉的数
- if(nWiner==order[i+1])
- {
- result[--count]=order[i];//排名在后面的直接
- order[count_left++]=order[i+1];//排名在前面的
- }
- else{
- result[--count]=order[i+1];
- order[count_left++]=order[i];
- }
- if(i!=0)
- {
- order[count_left++]=order[i+1];
- }
- if(count==0)
- result[0]=order[0];
- }
- }
- for(int i=0;i<6;i++)
- {
- cout<<result[i]<<endl;
- }
- return 0;
- }
#include <iostream>
#include <stack>
using namespace std;
/*order 顺序为pk顺序*/
int main()
{
int w[6][6] = { //排名 重复数
0,1,2,3,0,0, //4 3
1,1,2,1,1,1, //2 5
2,2,2,2,2,2, //1 6
3,1,2,3,3,3, //3 4
0,1,2,3,4,5, //6 1
0,1,2,3,5,5 //5 2
};
int order[6] = {1,3,4,2,0,5};
int result[6];
int count=6;
int count_left=0;
int flag;
while(count)
{
count_left=0;
for(int i=0;i<6;i=i+2)
{
int nWiner = *((int*)w + 6 * order[i] + order[i+1]);//取两个数交叉的数
if(nWiner==order[i+1])
{
result[--count]=order[i];//排名在后面的直接
order[count_left++]=order[i+1];//排名在前面的
}
else{
result[--count]=order[i+1];
order[count_left++]=order[i];
}
if(i!=0)
{
order[count_left++]=order[i+1];
}
if(count==0)
result[0]=order[0];
}
}
for(int i=0;i<6;i++)
{
cout<<result[i]<<endl;
}
return 0;
}
三,源码(利用模板list)
- #include <stdio.h>
- #include <list>
- #include <iostream>
- using namespace std;
- void raceResult(int** w, int* order, int* result, int n)
- {
- list<int> winer;
- int count = n;
- while(n)
- {
- winer.push_front(order[--n]);
- }
- int resultNum = count - 1;
- int nFirst, nSecond;
- int round = 1;
- while(winer.size() > 1)
- {
- //一轮开始
- cout<<endl<<"round "<<round++<<endl;
- list<int>::iterator it = winer.begin();
- while (it != winer.end())
- {
- nFirst = *it;
- if (++it == winer.end())
- {
- //轮空
- cout<<nFirst<<" rest this round"<<endl;
- }
- else
- {
- nSecond = *it; //已经向后移动
- int nWiner = *((int*)w + count * nFirst + nSecond);//取两个数交叉的数
- if (nWiner == nFirst)
- {
- it = winer.erase(it);
- result[resultNum--] = nSecond;
- cout<<nFirst<<" kick out "<<nSecond<<endl;
- }
- else
- {
- it = winer.erase(--it);
- result[resultNum--] = nFirst;
- ++it;
- cout<<nSecond<<" kick out "<<nFirst<<endl;
- }
- }
- }
- }
- if (winer.size() == 1)
- {
- result[0] = winer.front();
- }
- cout<<endl<<"final result: ";
- int nPlace = 0;
- while(nPlace < count)
- {
- :cout<<endl<<result[nPlace++];
- }
- }
- void test()
- {
- //team 2>team 1>team 3>team 0>team 4>team 5
- int w[6][6] = {
- 0,1,2,3,0,0,
- 1,1,2,1,1,1,
- 2,2,2,2,2,2,
- 3,1,2,3,3,3,
- 0,1,2,3,4,5
- };
- int order[6] = {1,3,4,2,0,5};
- int result[6] = {-1};
- raceResult((int**)w, order, result, 6);
- getchar();
- }
- //自己加上主函数,测试了下,结果竟正确..
- int main()
- {
- test();
- return 0;
- }
#include <stdio.h>
#include <list>
#include <iostream>
using namespace std;
void raceResult(int** w, int* order, int* result, int n)
{
list<int> winer;
int count = n;
while(n)
{
winer.push_front(order[--n]);
}
int resultNum = count - 1;
int nFirst, nSecond;
int round = 1;
while(winer.size() > 1)
{
//一轮开始
cout<<endl<<"round "<<round++<<endl;
list<int>::iterator it = winer.begin();
while (it != winer.end())
{
nFirst = *it;
if (++it == winer.end())
{
//轮空
cout<<nFirst<<" rest this round"<<endl;
}
else
{
nSecond = *it; //已经向后移动
int nWiner = *((int*)w + count * nFirst + nSecond);//取两个数交叉的数
if (nWiner == nFirst)
{
it = winer.erase(it);
result[resultNum--] = nSecond;
cout<<nFirst<<" kick out "<<nSecond<<endl;
}
else
{
it = winer.erase(--it);
result[resultNum--] = nFirst;
++it;
cout<<nSecond<<" kick out "<<nFirst<<endl;
}
}
}
}
if (winer.size() == 1)
{
result[0] = winer.front();
}
cout<<endl<<"final result: ";
int nPlace = 0;
while(nPlace < count)
{
:cout<<endl<<result[nPlace++];
}
}
void test()
{
//team 2>team 1>team 3>team 0>team 4>team 5
int w[6][6] = {
0,1,2,3,0,0,
1,1,2,1,1,1,
2,2,2,2,2,2,
3,1,2,3,3,3,
0,1,2,3,4,5
};
int order[6] = {1,3,4,2,0,5};
int result[6] = {-1};
raceResult((int**)w, order, result, 6);
getchar();
}
//自己加上主函数,测试了下,结果竟正确..
int main()
{
test();
return 0;
}
///
round 1
1 kick out 3
2 kick out 4
0 kick out 5
round 2
2 kick out 1
0 rest this round
round 3
2 kick out 0
final result:
2
0
1
5
4
3
/