zoukankan      html  css  js  c++  java
  • 【100题】第三十六 比赛淘汰问题(谷歌笔试)

    一,题目:(谷歌笔试)

          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 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;
    }


    ///////////////////////////////////////////////

    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
    /////////////////////////////////////////////////


  • 相关阅读:
    字符串类型
    数据类型之整型
    数据类型
    两个版本的区别
    变量
    DHCP
    MySQL数据库编译及入门
    NFS网络文件系统
    Rsync 数据同步
    互联网数据分享平台
  • 原文地址:https://www.cnblogs.com/secbook/p/2655011.html
Copyright © 2011-2022 走看看