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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值