您的位置:首页 > 编程语言

腾讯2016研发工程师编程题(2道)

2016-07-07 11:58 381 查看
1.生成格雷码

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

测试样例:1

返回结果:["0","1"]

方法一:递归法

考点:n位格雷码的排列中,其低n-1位排列是对称的。递归的思想体现在n位gray码由n-1位gray码生成。

举例:

假设求n=3的gray码,首先已知n=2的gray码是(00,01,11,10),那么n=3的gray码其实是对n=2的gray码首位(最高位)添加0或1后生成的。

添加0后变成(000,001,011,010)

添加1后变成(110,111,101,100)(注意逆序)

组合在一起是3位的gray码(000,001,011,010,110,111,101,100)

#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
vector<string> getGray(int n) {
vector<string> grayCode;
if(n == 1) {
grayCode.push_back("0");
grayCode.push_back("1");
return grayCode;
}
vector<string> last_grayCode = getGray(n - 1);

for(int i = 0; i < last_grayCode.size(); ++i) {
grayCode.push_back("0" + last_grayCode[i]);
}
for(int i = last_grayCode.size() - 1; i >= 0 ; --i) {
grayCode.push_back("1" + last_grayCode[i]);
}
return grayCode;
}
};

//main 函数是为了测试自己添加的
int main()
{
int n;
cin >> n;
Solution syq;
vector<string> ans = syq.getGray(n);
for(int i = 0; i < ans.size(); ++i) {
cout << ans[i] << endl;
}
return 0;
}


方法二:非递归法

考点:二进制与对应的格雷码的转换公式:格雷码 = 二进制码^(二进制码右移一位)

#include <bits/stdc++.h>

using namespace std;

class Solution
{
public:
string getBinStr(int num, int n) {
string binaryStr = "";
while(num) {
int remain = num % 2;
//string remainStr = to_string(remain);
string remainStr;
stringstream ss;
ss << remain;
ss >>  remainStr;
binaryStr = remainStr + binaryStr;//新的余数放在高位
num = num / 2;
n--;
}
while(n--) {
binaryStr = "0" + binaryStr;//n位格雷码,不足位数的前面补“0”
}
return binaryStr;
}
vector<string> getGray(int n)
{
int size = 1 << n;
vector<string> grayCode;
for(int i = 0; i < size; ++i)
{
int tmp = i ^ (i >> 1);//二进制与对应的格雷码的转换公式:格雷码 = 二进制码^(二进制码右移一位)
string grayStr = getBinStr(tmp, n);
grayCode.push_back(grayStr);
}
return grayCode;
}
};

//main 函数是自己为了测试添加的
int main()
{
int n;
cin >> n;
Solution syq;
vector<string> ans = syq.getGray(n);
for(int i = 0; i < ans.size(); ++i) {
cout << ans[i] << endl;
}
return 0;
}


2.微信红包

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

给定一个红包的金额数组gifts及它的大小n,请返回所求红包的金额。若没有金额超过总数的一半,返回0。
测试样例:[1,2,3,2,2],5

返回结果:2

方法一:中位数法
如果一个给定的数组中存在一个数字,它的出现次数超过一半,那么将数组排序后这个数字一定出现在中位数的位置。注意结果有可能并不存在这样的数。

#include <bits/stdc++.h>

using namespace std;

class Gift {
public:
int getValue(vector<int> gifts, int n) {
sort(gifts.begin(), gifts.end());
int ans = gifts[n/2];
int cout = 0;
for(int i = 0; i < n; ++i) {
if(gifts[i] == ans)
++cout;
}
return cout > n/2 ? ans : 0;
}
};

//main 函数是自己为了测试添加的
int main() {
int n;
Gift gift;
while(cin >> n) {
vector<int> syq(n);
for(int i = 0; i < n; ++i) {
cin >> syq[i];
}
cout << gift.getValue(syq, n) << endl;
}
return 0;
}


方法二:不同数字两两消除法(适用于所求的数字一定存在,见 LeetCode169 Majority Element)

class Solution {
public:
int majorityElement(vector<int>& nums) {
int ans = nums[0];
int cnt = 0;
for(int i = 0; i < nums.size(); ++i) {
if(ans == nums[i]) cnt++;
else cnt--;
if(cnt == 0) ans = nums[i+1];
}
return ans;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程 腾讯