腾讯2016年研发工程师编程题--完全解析

来源:互联网 发布:单片机中断程序编写 编辑:程序博客网 时间:2024/06/07 22:48

前言

虽然腾讯2016年研发工程师编程题并不是很难,但是两道题目还是值得讲一讲。

1.生成格雷码

在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同, 则称这种编码为格雷码(Gray Code),请编写一个函数,使用递归的方法生成N位的格雷码。
给定一个整数n,请返回n位的格雷码,顺序为从0开始。
测试样例:
1
返回:[“0”,”1”]

题目分析
思路1:递归生成码表

1)1位格雷码有两个码字

2)(n+1)位格雷码中的前2n个码字等于n位格雷码的码字,按顺序书写,加前缀0

3)(n+1)位格雷码中的后2n个码字等于n位格雷码的码字,按逆序书写,加前缀1[4]

4)n+1位格雷码的集合 = n位格雷码集合(顺序)加前缀0 + n位格雷码集合(逆序)加前缀1

上面是啥意思呢?简单点就是n+1位长的格雷码是所有n位长的格雷码每一位前面加0,和每一位前面加1构成的。如下图:

这里写图片描述
代码1

import java.util.*;public class GrayCode {    public String[] getGray(int n) {                 if(n==0)              return null;          String []grays=new String[(int) Math.pow(2, n)];          if(n==1)          {              grays[0]="0";              grays[1]="1";          }          else {            String []subgrays=getGray(n-1);            for(int i=0;i<2*subgrays.length;++i)            {                if(i<subgrays.length)                    grays[i]="0"+subgrays[i];                    //加"0"                else {                    grays[i]="1"+subgrays[2*subgrays.length-i-1];                    //加“1”是数组从后往前加,                }            }        }         return grays;      }}

思路2:异或转换
此方法从对应的n位二进制码字中直接得到n位格雷码码字,步骤如下:

对n位二进制的码字,从右到左,以0到n-1编号

如果二进制码字的第i位和i+1位相同,则对应的格雷码的第i位为0,否则为1(当i+1=n时,二进制码字的第n位被认为是0,即第n-1位不变)

例如:二进制码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

因此如果先从小到大求出而进制码,再使用上面的异或方法将二进制码转换为格雷码,此方法没有第一种方法好。

//获得长度为n的二进制码,此时还不是格雷码。 public static ArrayList<String> getGray(int n,String str)     {         if(n==0)         {             list.add(str);             return list;         }          getGray(n-1,str+'0');           getGray(n-1,str+'1');          return list;                     }//将二进制码转化为格雷码    public static String toGray(String str)     {         StringBuffer sb=new StringBuffer();         sb.append(str.charAt(0));         for(int i=1;i<str.length();i++)         {             sb.append(str.charAt(i-1)==str.charAt(i)?'0':'1');         }         return sb.toString();     }

长度为n的二进制码构成一棵高度为n+1的二叉树如下长度为2的二进制码:
这里写图片描述
序遍历这棵二叉树得到{“00” ,”01”,”10”,”11”}二进制序列然后将序列中的每一个使用上面说的异或方法就可以转化成{“00” ,”01”,”11”,”10”}的格雷码序列了。

2.微信红包

春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。
给定一个红包的金额数组gifts及它的大小n,请返回所求红包的金额。
若没有金额超过总数的一半,返回0。
测试样例:
[1,2,3,2,2],5
返回:2

题目分析
这道题有好几个思路,第一种将数组排序然后获取数组n/2处的数,如果一个数的个数超过数组长度的一半,那么排序后,中间位置肯定是该数,但是如果没有超过数组一半的数,就要将n/2处的数计算个数有没有超过n/2个。这种方法没什么好说的。
遍历数组将数组中任意两个不同的元素删除,那么最后剩下的元素一定是超过数组一半的数。

public static int getValue(int[] gifts, int n) {        int index=0;        int count=0;        for(int i=0;i<n-1;i++)        {            if(count<=0)            {                index=i;            }            if(gifts[i]==gifts[i+1])            {                count++;            }            else {                count--;            }        }        if(count<=0)            return 0;        return gifts[index];    }
原创粉丝点击