zoukankan      html  css  js  c++  java
  • 腾讯2016编程笔试题

    1、在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code)。请编写一个函数,使用递归方法生成N位的格雷码,并且保证这个函数的健壮性。

    首先的搞清楚格雷码是什么,百度百科

    生成格雷码的方法很多,百科中提到几种生成格雷码的方法,其中包括如下几种:

    ①递归法:

    1. 1位格雷码有两个码字;
    2. (n+1)位格雷码中的前2n个码字等于n位格雷码的码字,按顺序书写,加前缀0;
    3. (n+1)位格雷码中的后2n个码字等于n位格雷码的码字,按逆序书写,加前缀1;

    实现代码:

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    vector<string> RecursiveGrayCode(int N)
    {
        vector<string> temp;
        if (1 == N)
        {
            temp.push_back("0");
            temp.push_back("1");
            return temp;
        }
        vector<string> temp1 = RecursiveGrayCode(N-1);
    
        int size = temp1.size();
        int i=0;
    
        for (i=0;i<size;i++)
        {
            temp.push_back("0"+temp1[i]);
        }
    
        for (i=size-1;i>=0;i--)
        {
            temp.push_back("1"+temp1[i]);
        }
    
        return temp;
    }
    
    void GrayCode(int N)
    {
        if (N<=0)
        {
            cout << "Error
    ";
            return ;
        }
        vector<string> result = RecursiveGrayCode(N);
        for (int i=0;i<result.size();i++)
        {
            cout << result[i]<<endl;
        }
    }
    
    int main()
    {
        GrayCode(4);
        return 0;
    }

    ②异或转换:

    二进制码-->格雷码

    1. 对n位二进制的码字,从右到左,以0到n-1编号;
    2. 如果二进制码字的第i位和i+1位相同,则对应的格雷码的第i位为0,否则为1(当i+1=n时,二进制码字的第n位被认为是0,即第n-1位不变);

    公式表示:

      Gi=Bi^Bi+1(G:格雷码,B:二进制码)
    例如:二进制码0101,为4位数,所以其所转为之格雷码也必为4位数,因此可取转成之二进位码第五位为0,即0 b3 b2 b1 b0。
    0 xor 0=0,所以g3=0
    0 xor 1=1,所以g2=1
    1 xor 0=1,所以g1=1
    0 xor 1=1,所以g0=1
    因此所转换为之格雷码为0111
     
    代码:
     
     1 string BinaryCodeToGrayCode(string binaryCode)
     2 {
     3     string GrayCode="";
     4     int size = binaryCode.length();
     5     bool c;
     6     bool temp=0;
     7     bool bit;
     8     for (int i=0;i<size;i++)
     9     {
    10         bit = binaryCode[i]-'0';
    11         c=temp^bit;
    12         if (c)
    13         {
    14             GrayCode +="1";
    15         }
    16         else
    17         {
    18             GrayCode +="0";
    19         }
    20         
    21         temp = bit;
    22 
    23     }
    24     return GrayCode;
    25 }

    格雷码-->二进制码

      从左边第二位起,将每位与左边一位解码后的值异或,作为该位解码后的值(最左边一位依然不变)。依次异或,直到最低位。依次异或转换后的值(二进制数)就是格雷码转换后二进制码的值。

     公式表示:

     Bi=Gi^Bi+1 (G:格雷码,B:二进制码)
    举例:
    如果采集器器采到了格雷码:1010
    就要将它变为自然二进制:
    0 与第四位 1 进行异或结果为 1
    上面结果1与第三位0异或结果为 1
    上面结果1与第二位1异或结果为 0
    上面结果0与第一位0异或结果为 0
    因此最终结果为:1100 这就是二进制码即十进制 12

    实现代码:

     1 string GrayCodeToBinaryCode(string GrayCode)
     2 {
     3     string binaryCode="";
     4     int size = GrayCode.length();
     5     bool c;
     6     bool temp=0;
     7     bool bit;
     8     for (int i=0;i<size;i++)
     9     {
    10         bit = GrayCode[i]-'0';
    11         c=temp^bit;
    12         if (c)
    13         {
    14             binaryCode +="1";
    15         }
    16         else
    17         {
    18             binaryCode +="0";
    19         }
    20         
    21         temp = c;
    22 
    23     }
    24     return binaryCode;
    25 }

    2、题目如图所示,求出所有满足条件的情况:

    这道题的第一思路就是找出隐含关系,然后暴力求解。假设所填空格从上往下,从左往右依次为a,b,c,d,e,f,g,h即:

    a b 9
    c d e
    f g h

    通过找隐含关系可以找到如下关系:

    a+b=13;

    0<=a<=4;

    e+h=5;

    0<=e<=5;

    因为b最大为13,所以有b-d*g==4可知,d<=9,g<=9且d,g都不能为0;

    1<=f<=100

    接下来就是暴力求解,代码如下:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 void main()
     5 {
     6     int a,b,c,d,e,f,g,h;
     7     for (a=0;a<=4;a++)
     8     {
     9         b=13-a;
    10         for (e=0;e<=5;e++)
    11         {
    12             h=5-e;
    13             
    14             for (d=1;d<=9;d++)
    15             {
    16                 c=d*e+4;
    17                 for (g=1;g<=9;g++)
    18                 {
    19                 
    20                     for (f=1;f<=100;f++)
    21                     {
    22                         if (c%f == 0)
    23                         {
    24                             if ((a+c/f == 4)&&(b-d*g == 4)&&(f+g-h == 4))
    25                             {
    26                                 cout << a << " "<< b <<" "<<9<<endl;
    27                                 cout << c << " "<< d <<" "<<e<<endl;
    28                                 cout << f << " "<< g <<" "<<h<<endl;
    29 
    30                             }
    31                         }
    32                         else
    33                             continue;
    34                         
    35                     }
    36                 }
    37             }
    38                 
    39         }
    40     }
    41 
    42 }

    3. 如图所示,系统中有三个进程Producer,Transmitter和Consumer。Producer和Transmitter共用缓冲区ProduceBuf,Consumer和Transmitter共用缓冲区ConsumeBuf。

    Producer进程负责不断地将输入信息送入ProduceBuf;Transmitter进程负责从ProduceBuf中取出信息进行处理,并将处理结果送到ConsumeBuf;Consumer进程负责从ConsumeBuf中读取结果并输出。 

    假设ProduceBuf中最多可放12个信息,现已放入了3个信息;ConSumeBuf最多可放6个信息。试写出正确实现进程Producer,Transmitter和Consumer的同步与互斥的算法 (要求:用类C语言描述,条理清楚,注释恰当;)

    分析:

    要解决这道题目,首先需要掌握一般的producer和consumer问题(操作系统经典问题)

     附上本科操作系统课程实验代码

      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<windows.h>
      4 #include<stdio.h>
      5 #include<ctime>
      6 using namespace std;
      7 
      8 /*****定义缓冲区单元******/
      9  
     10 typedef int buffer_item;
     11 #define BUFFER_SIZE 5
     12 
     13 buffer_item buffer[BUFFER_SIZE+1];//利用数组模拟缓冲区,因为可使用的个数比数组个数少一个
     14 int first,last;//first指向已经插入的第一个单元,last指向下一个可插入的单元
     15 HANDLE mutex,empty,full;
     16 
     17 int insert_item(buffer_item item){
     18     /*insert a buffer item into buffer,
     19       return 0 if successful,otherwise 
     20       return -1 indicating an error condition
     21     */
     22 
     23     if((last+1)%BUFFER_SIZE==first)//判断满?
     24         return -1;//Yes
     25     else{
     26         buffer[last]=item;
     27         last = (last+1)%BUFFER_SIZE;
     28         return 0;
     29     }
     30 }
     31 
     32 int remove_item(buffer_item* item){
     33     /*romove a buffer item into buffer,
     34       return 0 if successful,otherwise 
     35       return -1 indicating an error condition
     36     */
     37 
     38     if(first == last)//判断空?
     39         return -1;//Yes
     40     else{
     41         *item=buffer[first];
     42         first = (first + 1)%BUFFER_SIZE;
     43         return 0;
     44     }
     45 }
     46 
     47 DWORD WINAPI Producer(LPVOID Param){
     48     int i = *(int *)Param;
     49     int ran;
     50     srand(time(0));
     51     while(true){
     52         Sleep(rand()%1000);
     53         //参照书本算法P177页
     54         WaitForSingleObject(empty,INFINITE);
     55         WaitForSingleObject(mutex,INFINITE);//当有多个Producer线程时,这个变量是有用的
     56         /*临界区*/
     57             ran = rand();
     58             cout << "producer produced " << ran <<" by " <<i<<endl;
     59             if(insert_item(ran)==-1)
     60                 cout<<"insert data error!
    ";
     61         ReleaseMutex(mutex);
     62         ReleaseSemaphore(full,1,NULL);//1表示递增信号量值(步长)
     63     }
     64 
     65     return 0;
     66 }
     67 
     68 DWORD WINAPI Consumer(LPVOID Param){
     69     int i = *(int *)Param;
     70     buffer_item ran;
     71     srand(time(0));
     72     while(true){
     73         Sleep(rand()%1000);//随机等待也是为了防止各个线程等待时间一样,导致工作方式同步
     74         //参照书本算法P177页
     75         WaitForSingleObject(full,INFINITE);
     76         WaitForSingleObject(mutex,INFINITE);
     77         /*临界区*/
     78             //ran = rand();
     79             
     80             if(remove_item(&ran)==-1)
     81                 cout<<"remove data error!
    ";
     82             else
     83                 cout << "consumer consumed " << ran <<" by " <<i<< endl;
     84         ReleaseMutex(mutex);
     85         ReleaseSemaphore(empty,1,NULL);//1表示递增信号量值(步长)
     86     }
     87 
     88     return 0;
     89 }
     90 
     91 int main(int argc,char* argv){
     92 
     93     /*初始化缓冲*/
     94     first=last=0;
     95 
     96     int sleeptime;//睡眠时间
     97     int proNum,conNum;//生产者和消费者线程数量
     98     HANDLE *ThreadHandleOfProducer,*ThreadHandleOfConsumer;//线程句柄
     99     unsigned long *ThreadIDProducer,*ThreadIDConsumer;//线程ID数组
    100     int * ParamOfProducer,*ParamOfConsumer;
    101     /*
    102     sleeptime=atoi(argv[1]);
    103     proNum=atoi(argv[2]);
    104     conNum=atoi(argv[3]);
    105     */
    106 
    107     sleeptime = 1000;
    108     proNum=3;
    109     conNum=3;
    110 
    111     ThreadHandleOfProducer = new HANDLE[proNum];
    112     ThreadHandleOfConsumer = new HANDLE[conNum];
    113     ThreadIDProducer = new unsigned long[proNum];
    114     ThreadIDConsumer = new unsigned long[conNum];
    115     ParamOfProducer = new int[proNum];
    116     ParamOfConsumer = new int[conNum];
    117     
    118     /*信号量的声明*/
    119     mutex=CreateMutex(NULL,FALSE,NULL);
    120     empty=CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL);//第二个参数是初值,第三个是最大值
    121     full=CreateSemaphore(NULL,0,BUFFER_SIZE+1,NULL);//第二个参数是初值,第三个是最大值
    122     //创建生产者线程
    123     for(int i =0;i<proNum;i++){
    124         ParamOfProducer[i]=i+1;
    125         ThreadHandleOfProducer[i]=CreateThread(
    126             NULL,//default
    127             0,//default stack size
    128             Producer,//thread function
    129             &ParamOfProducer[i],//parameter to thread function
    130             0,//default creation flags;
    131             &ThreadIDProducer[i]//返回线程的ID
    132             );
    133     }
    134     //创建消费者线程
    135     for(int j =0;j<conNum;j++){
    136         ParamOfConsumer[j]=j+1;
    137         ThreadHandleOfConsumer[j]=CreateThread(
    138             NULL,//default
    139             0,//default stack size
    140             Consumer,//thread function
    141             &ParamOfConsumer[j],//parameter to thread function
    142             0,//default creation flags;
    143             &ThreadIDConsumer[j]//返回线程的ID
    144             );
    145     }
    146 
    147     Sleep(sleeptime);
    148     return 0;
    149 }

     仔细研究上面的代码,可以发现第108和109行,其实现了多个生产者和多个消费者,并且需要注意各个信号量的初始值。本题需要解决两个buffer,生产者buffer和消费者buffer各一个。按照上面代码思路,解决此题的需要再增加几个信号量,添加一个transmitter函数,其功能是作为一个传递者,代码实现如下(仅供参考),其主要部分是transmitter函数,transmitter必须在produceBuffe有数据,并且consumeBuffer不是满的情况下才能执行操作:

      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<windows.h>
      4 #include<stdio.h>
      5 #include<ctime>
      6 using namespace std;
      7 
      8 /*****定义缓冲区单元******/
      9  
     10 typedef int buffer_item;
     11 #define PRODUCE_BUFFER_SIZE 12
     12 #define CONSUME_BUFFER_SIZE 6
     13 
     14 
     15 buffer_item producebuffer[PRODUCE_BUFFER_SIZE+1];//利用数组模拟缓冲区,因为可使用的个数比数组个数少一个
     16 buffer_item consumebuffer[CONSUME_BUFFER_SIZE+1];//利用数组模拟缓冲区,因为可使用的个数比数组个数少一个
     17 
     18 int firstofproduce,lastofproduce,firstofconsume,lastofconsume;//first指向已经插入的第一个单元,last指向下一个可插入的单元
     19 HANDLE mutexofproduce,emptyofproduce,fullofproduce;//produce buffer
     20 HANDLE mutexofconsume,emptyofconsume,fullofconsume;//consume buffer
     21 HANDLE mutexoftransimitter;
     22 
     23 int insert_item_pro(buffer_item item){
     24     
     25     if((lastofproduce+1)%PRODUCE_BUFFER_SIZE==firstofproduce)//判断满?
     26         return -1;//Yes
     27     else{
     28         producebuffer[lastofproduce]=item;
     29         lastofproduce = (lastofproduce+1)%PRODUCE_BUFFER_SIZE;
     30         return 0;
     31     }
     32 }
     33 
     34 int insert_item_con(buffer_item item){
     35 
     36     if((lastofconsume+1)%CONSUME_BUFFER_SIZE==firstofconsume)//判断满?
     37         return -1;//Yes
     38     else{
     39         consumebuffer[lastofconsume]=item;
     40         lastofconsume = (lastofconsume+1)%CONSUME_BUFFER_SIZE;
     41         return 0;
     42     }
     43 }
     44 
     45 int remove_item_pro(buffer_item* item){
     46     
     47     if(firstofproduce == lastofproduce)//判断空?
     48         return -1;//Yes
     49     else{
     50         *item=producebuffer[firstofproduce];
     51         firstofproduce = (firstofproduce + 1)%PRODUCE_BUFFER_SIZE;
     52         return 0;
     53     }
     54 }
     55 
     56 int remove_item_con(buffer_item* item){
     57     
     58     if(firstofconsume == lastofconsume)//判断空?
     59         return -1;//Yes
     60     else{
     61         *item=consumebuffer[firstofconsume];
     62         firstofconsume = (firstofconsume + 1)%CONSUME_BUFFER_SIZE;
     63         return 0;
     64     }
     65 }
     66 
     67 
     68 DWORD WINAPI Producer(LPVOID Param){
     69     int i = *(int *)Param;
     70     buffer_item ran;
     71     srand(time(0));
     72     while(true){
     73         Sleep(rand()%1000);
     74         //参照书本算法P177页
     75         WaitForSingleObject(emptyofproduce,INFINITE);
     76         WaitForSingleObject(mutexofproduce,INFINITE);
     77         /*临界区*/
     78             ran = rand();
     79             cout << "producer produced " << ran <<" by " <<i<<endl;
     80             if(insert_item_pro(ran)==-1)
     81                 cout<<"insert data error!
    ";
     82         ReleaseMutex(mutexofproduce);
     83         ReleaseSemaphore(fullofproduce,1,NULL);//1表示递增信号量值(步长)
     84     }
     85 
     86     return 0;
     87 }
     88 
     89 DWORD WINAPI Transmitter(LPVOID Param){
     90     int i = *(int *)Param;
     91     buffer_item ran;
     92     srand(time(0));
     93     
     94     Sleep(rand()%1000);
     95     //参照书本算法P177页
     96     while (true)
     97     {
     98         Sleep(rand()%1000);
     99         WaitForSingleObject(fullofproduce,INFINITE);//等到produce buffer 队列里面有内容
    100         WaitForSingleObject(emptyofconsume,INFINITE);//此时consume buffer 队列有空位
    101 
    102         WaitForSingleObject(mutexoftransimitter,INFINITE);
    103         
    104         if(remove_item_pro(&ran)==-1)
    105             cout<<"remove data error!
    ";
    106 
    107         //数据处理
    108         cout << "transimitter consumed " << ran <<" by " <<i<<endl;
    109         ran = ran + 10;
    110         
    111         if (insert_item_con(ran) == -1)
    112         {
    113             cout<<"insert data error!
    ";
    114         }
    115 
    116         cout << "transimitter produced " << ran <<" by " <<i<<endl;
    117         ReleaseMutex(mutexoftransimitter);
    118 
    119         ReleaseSemaphore(fullofconsume,1,NULL);//可以理解为fullofconsume+1
    120         ReleaseSemaphore(emptyofproduce,1,NULL);//1表示递增信号量值(步长)
    121     }
    122 
    123     return 0;
    124 }
    125 
    126 DWORD WINAPI Consumer(LPVOID Param){
    127     int i = *(int *)Param;
    128     buffer_item ran;
    129     srand(time(0));
    130     while(true){
    131         Sleep(rand()%1000);
    132         //参照书本算法P177页
    133         WaitForSingleObject(fullofconsume,INFINITE);
    134         WaitForSingleObject(mutexofconsume,INFINITE);
    135         /*临界区*/
    136             //ran = rand();
    137             
    138             if(remove_item_con(&ran)==-1)
    139                 cout<<"remove data error!
    ";
    140             else
    141                 cout << "consumer consumed " << ran <<" by " <<i<< endl;
    142         ReleaseMutex(mutexofconsume);
    143         ReleaseSemaphore(emptyofconsume,1,NULL);//1表示递增信号量值(步长)
    144     }
    145 
    146     return 0;
    147 }
    148 
    149 int main(int argc,char* argv){
    150 
    151     /*初始化缓冲*/
    152     firstofproduce=0;
    153     firstofconsume=0;
    154     lastofproduce=2;
    155     lastofconsume=0;
    156 
    157     //初始化producebuffer中前三个数
    158     producebuffer[0]=1;
    159     producebuffer[1]=2;
    160     producebuffer[2]=3;
    161 
    162 
    163     int sleeptime;//睡眠时间
    164     int proNum,conNum,traNum;//生产者和消费者线程数量
    165     HANDLE *ThreadHandleOfProducer,*ThreadHandleOfConsumer,*ThreadHandleOfTransimitter;//线程句柄
    166     unsigned long *ThreadIDProducer,*ThreadIDConsumer,*ThreadIDTransimitter;//线程ID数组
    167     int * ParamOfProducer,*ParamOfConsumer,*ParamOfTransimitter;
    168     /*
    169     sleeptime=atoi(argv[1]);
    170     proNum=atoi(argv[2]);
    171     conNum=atoi(argv[3]);
    172     */
    173 
    174     sleeptime = 10000;
    175     proNum=1;
    176     conNum=1;
    177     traNum=1;
    178 
    179     ThreadHandleOfProducer = new HANDLE[proNum];
    180     ThreadHandleOfConsumer = new HANDLE[conNum];
    181     ThreadHandleOfTransimitter = new HANDLE[traNum];
    182     ThreadIDProducer = new unsigned long[proNum];
    183     ThreadIDConsumer = new unsigned long[conNum];
    184     ThreadIDTransimitter = new unsigned long[traNum];
    185     ParamOfProducer = new int[proNum];
    186     ParamOfConsumer = new int[conNum];
    187     ParamOfTransimitter = new int[traNum];
    188     
    189     /*信号量的声明*/
    190     mutexofproduce=CreateMutex(NULL,FALSE,NULL);
    191     mutexofconsume=CreateMutex(NULL,FALSE,NULL);
    192     mutexoftransimitter=CreateMutex(NULL,FALSE,NULL);
    193 
    194     emptyofproduce=CreateSemaphore(NULL,PRODUCE_BUFFER_SIZE,PRODUCE_BUFFER_SIZE,NULL);//第二个参数是初值,第三个是最大值
    195     fullofproduce=CreateSemaphore(NULL,3,PRODUCE_BUFFER_SIZE,NULL);//第二个参数是初值,第三个是最大值
    196 
    197     emptyofconsume=CreateSemaphore(NULL,CONSUME_BUFFER_SIZE,CONSUME_BUFFER_SIZE,NULL);
    198     fullofconsume=CreateSemaphore(NULL,0,CONSUME_BUFFER_SIZE,NULL);
    199 
    200 
    201     //创建生产者线程
    202     for(int i =0;i<proNum;i++){
    203         ParamOfProducer[i]=i+1;
    204         ThreadHandleOfProducer[i]=CreateThread(
    205             NULL,//default
    206             0,//default stack size
    207             Producer,//thread function
    208             &ParamOfProducer[i],//parameter to thread function
    209             0,//default creation flags;
    210             &ThreadIDProducer[i]//返回线程的ID
    211             );
    212     }
    213 
    214     //创建传递者线程
    215     for(int j =0;j<traNum;j++){
    216         ParamOfConsumer[j]=j+1;
    217         ThreadHandleOfTransimitter[j]=CreateThread(
    218             NULL,//default
    219             0,//default stack size
    220             Transmitter,//thread function
    221             &ParamOfConsumer[j],//parameter to thread function
    222             0,//default creation flags;
    223             &ThreadIDConsumer[j]//返回线程的ID
    224         );
    225     }
    226 
    227     //创建消费者线程
    228     for(int j =0;j<conNum;j++){
    229         ParamOfConsumer[j]=j+1;
    230         ThreadHandleOfConsumer[j]=CreateThread(
    231             NULL,//default
    232             0,//default stack size
    233             Consumer,//thread function
    234             &ParamOfConsumer[j],//parameter to thread function
    235             0,//default creation flags;
    236             &ThreadIDConsumer[j]//返回线程的ID
    237             );
    238     }
    239 
    240     
    241 
    242     Sleep(sleeptime);
    243     return 0;
    244 }

     4. 春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。

    这道题有比较巧妙的解题算法,参考“编程之美----发帖水王”,代码如下

  • 相关阅读:
    性能测试七:jmeter进阶之文件上传下载、定时器
    性能测试六:jmeter进阶之Cookie与header管理器
    导出文本、表格、图像到PDF格式文件中(学习整理)
    数据库(学习整理)----7--Oracle多表查询,三种join连接
    反射(学习整理)----Class类和加载器ClassLoader类的整理
    反射(学习整理)----操作类、属性、方法!
    数据库(学习整理)----6--Oracle如何快速备份和多次备份数表数据
    数据库(学习整理)----5--Oracle常用的组函数
    数据库(学习整理)----4--Oracle数据查询(基础点1)
    Java小例子(学习整理)-----学生管理系统-控制台版
  • 原文地址:https://www.cnblogs.com/LCCRNblog/p/4796095.html
Copyright © 2011-2022 走看看