[笔试练习]美团笔试题

1.请设计一个算法,给一个字符串进行二进制编码,使得编码后字符串的长度最短。

输入描述:
每组数据一行,为待编码的字符串。保证字符串长度小于等于1000。


输出描述:
一行输出最短的编码后长度。

输入例子:
MT-TECH-TEAM

输出例子:
33

分析:哈夫曼编码的过程,用一个最小堆实现,将当前最小的两个数取出来,求和后继续推入堆中。

代码:

#include 
#include 
#include 
#include 
#include 
using namespace std;
int main() {
	string s;
	while (getline(cin, s)) {
		int ret=0;
		int n = s.size();
		sort(s.begin(), s.end());
		int cnt = 0;
		priority_queue, greater > heap;
		for (int i = 0, j; i < n;) {
			j = i;
			while (j < n && s[j] == s[i]) ++j;
			heap.push(j - i);
			i = j;
			++cnt;
		}
		for (int i = 0; i < cnt-1; i++) {
			int a = heap.top();
			heap.pop();
			int b = heap.top();
			heap.pop();
			heap.push(a+b);
			ret += a + b;
			

		}
		cout << ret << endl;

	}
	return 0;
}

2.对于一个由0..n的所有数按升序组成的序列,我们要进行一些筛选,每次我们取当前所有数字中从小到大的第奇数位个的数,并将其丢弃。重复这一过程直到最后剩下一个数。请求出最后剩下的数字。

输入描述:
每组数据一行一个数字,为题目中的n(n小于等于1000)。


输出描述:
一行输出最后剩下的数字。

输入例子:
500

输出例子:
255

分析(转的):因为是从0开始,所以第一轮移走的是二进制下最右边为0的位置(从0开始的偶数位置)上的数,然后我们发现第二轮各个number的位置等于number/2,即从number位置到number>>1位置,这时候我们依然移走二进制下最右边为0的位置(1(01)  5(101) 9(1001) ……它们第二轮对应的位置是0, 2, 4),最后剩一个数肯定是0到n中二进制下1最多的那个数,因为它每次的位置都是奇数位置。

代码:

#include 
using namespace std;
int main(){
    int n;
    while(cin>>n){
        int b=1;
        while(b>1)-1;
        cout<

3.

有一个二维数组(n*n),写程序实现从右上角到左下角沿主对角线方向打印。

给定一个二位数组arr及题目中的参数n,请返回结果数组。

测试样例:
[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]],4
返回:[4,3,8,2,7,12,1,6,11,16,5,10,15,9,14,13]

分析:矩阵打印题,写的有点麻烦了。

代码:

class Printer {
public:
    vector arrayPrint(vector > arr, int n) {
        vector ret;
        int k=0;
        int i=0;
        int j=n-1;
        while(k=0){
            for(int h=0;h<=k;h++){
                ret.push_back(arr[i+h][j+h]);
            }
            i++;
            k--;
        }

        return ret;
    }
};

4.

在股市的交易日中,假设最多可进行两次买卖(即买和卖的次数均小于等于2),规则是必须一笔成交后进行另一笔(即买-卖-买-卖的顺序进行)。给出一天中的股票变化序列,请写一个程序计算一天可以获得的最大收益。请采用实践复杂度低的方法实现。

给定价格序列prices及它的长度n,请返回最大收益。保证长度小于等于500。

测试样例:
[10,22,5,75,65,80],6
返回:87

分析:leetcode原题。。动态规划,买卖次数小于等于2,那么对于每一个点,找到这个点之前买卖一次能获得的最大收益,以及之后买卖一次获得的最大收益,找到这个前后和的最大值。

代码:

class Stock {
public:
    int maxProfit(vector prices, int n) {
        vector preprofit(n,0);
        vector postprofit(n,0);
        int curMin=prices[0];
        int pre=0;
        for(int i=1;i=0;i--){
            curMax=max(curMax,prices[i]);
            post=max(post,curMax-prices[i]);
            postprofit[i]=post;
        }
        int ret=0;
        for(int i=0;i


你可能感兴趣的:(笔试练习)