【100题】第三十六 比赛淘汰问题(谷歌笔试)

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没有任何关系。

       对应源码为:

  1. #include <iostream>  
  2. #include <stack>  
  3. using namespace std;  
  4. /*order 顺序为pk顺序*/  
  5. int main()  
  6. {  
  7.     int w[6][6] = {    //排名  重复数  
  8.         0,1,2,3,0,0,   //4      3  
  9.         1,1,2,1,1,1,   //2      5  
  10.         2,2,2,2,2,2,   //1      6  
  11.         3,1,2,3,3,3,   //3      4  
  12.         0,1,2,3,4,5,   //6      1  
  13.         0,1,2,3,5,5    //5      2  
  14.     };     
  15.     int order[6] = {1,3,4,2,0,5};    
  16.     int weight[6];//2,3,6,1,4,5   
  17.     int result[6];  
  18.     int max;  
  19.    for(int i=0;i<6;i++)  
  20.    {  
  21.      max=0;  
  22.      int temp[6]={0,0,0,0,0,0};  
  23.      for(int j=0;j<6;j++)  
  24.      {  
  25.         temp[w[i][j]]++;      
  26.      }  
  27.      for(int k=0;k<6;k++)//获取排名  
  28.      {  
  29.          if(max<temp[k])  
  30.               max=temp[k];//获取最大重复数  
  31.      }  
  32.       
  33.      weight[i]=7-max;//排名         
  34. }  
  35.   
  36.  int n=6;  
  37.  int count=6;  
  38.  int count_left=0;  
  39. int flag;  
  40.  while(count)  
  41.  {  
  42.      count_left=0;  
  43.        
  44.      for(int i=0;i<6;i=i+2)  
  45.      {  
  46.          
  47.          if(weight[order[i]]>weight[order[i+1]])  
  48.             {  
  49.                  
  50.                  
  51.                result[--count]=order[i];//排名在后面的直接   
  52.                order[count_left++]=order[i+1];//排名在前面的   
  53.             }  
  54.         else  
  55.             {  
  56.   
  57.                result[--count]=order[i+1];  
  58.                order[count_left++]=order[i];  
  59.             }  
  60.           
  61.           
  62.         if(i!=0)   
  63.          {  
  64.              order[count_left++]=order[i+1];  
  65.                
  66.          }  
  67.            
  68.          if(count==0)  
  69.            result[0]=order[0];  
  70.      }     
  71.        
  72.    //  cout<<"count "<<count<<endl;  
  73.       
  74.  }  
  75.   //result[0]=weight[order[i]];  
  76.     
  77.     for(int i=0;i<6;i++)  
  78.     {  
  79.         cout<<result[i]<<endl;  
  80.     }  
  81.       
  82.    return 0;  
  83. }  
#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;
}

上述源码中,明显的缺点就是,通过记录重复个数来判断哪个优先级高。这里完全可以根据两个元素行与列交叉处值来判断。

改进后源码:

  1. #include <iostream>  
  2. #include <stack>  
  3. using namespace std;  
  4. /*order 顺序为pk顺序*/  
  5. int main()  
  6. {  
  7.     int w[6][6] = {    //排名  重复数  
  8.         0,1,2,3,0,0,   //4      3  
  9.         1,1,2,1,1,1,   //2      5  
  10.         2,2,2,2,2,2,   //1      6  
  11.         3,1,2,3,3,3,   //3      4  
  12.         0,1,2,3,4,5,   //6      1  
  13.         0,1,2,3,5,5    //5      2  
  14.     };     
  15.     int order[6] = {1,3,4,2,0,5};    
  16.     int result[6];  
  17.   
  18. int count=6;  
  19. int count_left=0;  
  20. int flag;  
  21.   
  22.  while(count)  
  23.  {  
  24.      count_left=0;  
  25.        
  26.      for(int i=0;i<6;i=i+2)  
  27.      {  
  28.          
  29.         int nWiner = *((int*)w + 6 * order[i] + order[i+1]);//取两个数交叉的数  
  30.             
  31.            if(nWiner==order[i+1])  
  32.             {  
  33.                result[--count]=order[i];//排名在后面的直接   
  34.                order[count_left++]=order[i+1];//排名在前面的   
  35.             }   
  36.            else{  
  37.               
  38.                result[--count]=order[i+1];  
  39.                order[count_left++]=order[i];  
  40.            }   
  41.           
  42.           
  43.         if(i!=0)   
  44.          {  
  45.              order[count_left++]=order[i+1];  
  46.                
  47.          }  
  48.            
  49.          if(count==0)  
  50.            result[0]=order[0];  
  51.      }     
  52.        
  53.      
  54.       
  55.  }    
  56.     
  57.     for(int i=0;i<6;i++)  
  58.     {  
  59.         cout<<result[i]<<endl;  
  60.     }  
  61.       
  62.    return 0;  
  63. }  
#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)

  1. #include <stdio.h>     
  2. #include <list>     
  3. #include <iostream>    
  4. using namespace std;  
  5. void raceResult(int** w, int* order, int* result, int n)     
  6. {     
  7.     list<int> winer;     
  8.          
  9.     int count = n;     
  10.     while(n)     
  11.     {     
  12.         winer.push_front(order[--n]);     
  13.     }     
  14.          
  15.     int resultNum = count - 1;     
  16.     int nFirst, nSecond;     
  17.     int round = 1;     
  18.     while(winer.size() > 1)     
  19.     {     
  20.         //一轮开始     
  21.         cout<<endl<<"round "<<round++<<endl;     
  22.         list<int>::iterator it = winer.begin();     
  23.         while (it != winer.end())     
  24.         {     
  25.             nFirst = *it;     
  26.             if (++it == winer.end())     
  27.             {     
  28.                 //轮空     
  29.                 cout<<nFirst<<" rest this round"<<endl;     
  30.             }     
  31.             else    
  32.             {     
  33.                 nSecond = *it;   //已经向后移动   
  34.                   
  35.                 int nWiner = *((int*)w + count * nFirst + nSecond);//取两个数交叉的数  
  36.                    
  37.                 if (nWiner  == nFirst)     
  38.                 {     
  39.                     it = winer.erase(it);     
  40.                     result[resultNum--] = nSecond;     
  41.                     cout<<nFirst<<" kick out "<<nSecond<<endl;     
  42.                 }     
  43.                 else    
  44.                 {     
  45.                     it = winer.erase(--it);     
  46.                     result[resultNum--] = nFirst;     
  47.                     ++it;     
  48.                     cout<<nSecond<<" kick out "<<nFirst<<endl;     
  49.                 }     
  50.             }     
  51.         }     
  52.     }   
  53.         
  54.     if (winer.size() == 1)     
  55.     {     
  56.         result[0] = winer.front();     
  57.     }     
  58.     cout<<endl<<"final result: ";     
  59.     int nPlace = 0;     
  60.     while(nPlace < count)     
  61.     {     
  62.         :cout<<endl<<result[nPlace++];     
  63.     }     
  64. }  
  65.   
  66. void test()     
  67. {     
  68.     //team 2>team 1>team 3>team 0>team 4>team 5     
  69.     int w[6][6] = {     
  70.         0,1,2,3,0,0,     
  71.         1,1,2,1,1,1,     
  72.         2,2,2,2,2,2,     
  73.         3,1,2,3,3,3,     
  74.         0,1,2,3,4,5     
  75.     };     
  76.     int order[6] = {1,3,4,2,0,5};     
  77.     int result[6] = {-1};     
  78.     raceResult((int**)w, order, result, 6);     
  79.     getchar();     
  80. }  
  81. //自己加上主函数,测试了下,结果竟正确..  
  82. int main()  
  83. {  
  84.     test();  
  85.     return 0;  
  86. }  
#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
/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值