美团点评2016研发工程师编程题(二)
请设计一个算法,给一个字符串进行二进制编码,使得编码后字符串的长度最短。
每组数据一行,为待编码的字符串。保证字符串长度小于等于1000。
一行输出最短的编码后长度。
MT-TECH-TEAM
33
分析:哈夫曼编码的过程,用一个最小堆实现,将当前最小的两个数取出来,求和后继续推入堆中。
代码:
我的代码:
#include
#include
#include
using namespace std;
class Node {
public: int data;
Node* lchild;
Node* rchild;
Node(int data_input) {
data = data_input;
lchild = NULL;
rchild = NULL;
}
~Node() {
if(lchild == NULL) {
delete lchild;
}
if(rchild == NULL) {
delete rchild;
}
}
};
int num(string str, int predata[]) {
int num = 0;
for(int i = 0; i < str.length(); i++)
{
int flag = 0;;
for(int j = i - 1; j >= 0; j--)
{
flag = 0;
if(str[i] == str[j]) {
flag = 1;
break;
}
}
if(flag == 1) {
}
else if(flag == 0) {
predata[num] = str[i];
num++;
}
}
return num;
}
void nodenum(string str, int predata[],int data[], int length) {
for(int i = 0; i < length; i++) {
for(int j = 0; j < str.length(); j++) {
if(predata[i] == str[j]) {
data[i]++;
}
}
}
}
void sort(int data[], int l, int r) {
int i = l, j = r;
int flag = data[l];
do{
while(i <= j && data[i] < flag) {
i++;
}
while(i <= j && data[j] > flag) {
j--;
}
if(i <= j) {
swap(data[i], data[j]);
i++;
j--;
}
}while(i <= j);
if(i < r) {
sort(data, i, r);
}
if(j > l) {
sort(data, l, j);
}
}
int main() {
string str;
while(getline(cin, str)) {
int* predata = new int[str.length()];
int length = num(str, predata);
int* data = new int[length];
for(int i = 0; i < length; i++) {
data[i] = 0;
}
nodenum(str, predata, data, length);
sort(data, 0, length - 1);
priority_queue
for(int n = 0; n < length; n++) {
pq.push(data[n]);
}
int rec = 0;
for(int x = 0; x < length - 1; x++) {
int A = pq.top(); pq.pop();
int B = pq.top(); pq.pop();
rec += A + B;
pq.push(A + B);
}
cout << rec << endl;
}
/*
for(int m = 0; m < length; m++) {
cout << pq.top() << " ";
pq.pop();
}
cout << num(str, predata) << endl;
for(int j = 0; j < length; j++) {
printf("%d", data[j]);
}
*/
return 0;
}
对于一个由0..n的所有数按升序组成的序列,我们要进行一些筛选,每次我们取当前所有数字中从小到大的第奇数位个的数,并将其丢弃。重复这一过程直到最后剩下一个数。请求出最后剩下的数字。
每组数据一行一个数字,为题目中的n(n小于等于1000)。
一行输出最后剩下的数字。
500
255
249
253
255
257
499
不同于以上答案
package 美团;
import java.util.*;
import java.lang.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while(scan.hasNext()) {
int m = scan.nextInt();
List
for(int i = 0; i <= m; i++) {
list.add(i);
}
while(list.size() > 1) {
for(int i = list.size(); i >= 1; i--) {
if(i % 2 != 0) {
list.remove(i - 1);
}
}
}
System.out.println(list.get(0));
}
}
}
有一个二维数组(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]package 美团;
在股市的交易日中,假设最多可进行两次买卖(即买和卖的次数均小于等于2),规则是必须一笔成交后进行另一笔(即买-卖-买-卖的顺序进行)。给出一天中的股票变化序列,请写一个程序计算一天可以获得的最大收益。请采用实践复杂度低的方法实现。
给定价格序列prices及它的长度n,请返回最大收益。保证长度小于等于500。
[10,22,5,75,65,80],6
返回:87
package 美团;
import java.util.*;
public class Stock {
public int maxProfit(int[] prices, int n) {
int max = max(prices, 0, n -1 );
System.out.println(max);
for(int i = 0; i < n - 3; i++) {
if(max(prices, 0, i + 1) + max(prices, i + 2, n - 1) > max) {
max = max(prices, 0, i + 1) + max(prices, i + 2, n - 1);
}
//System.out.println(max);
}
return max;
// write code here
}
public int max(int[] prices, int l, int r) {
int max = prices[r] - prices[r - 1];
for(int i = r; i >= l; i--) {
for(int j = i - 1; j >= l; j--) {
if(prices[i] - prices[j] > max) {
max = prices[i] - prices[j];
}
}
}
//System.out.println(max);
return max;
}
public static void main(String[] args) {
Stock stock = new Stock();
int[] prices = {10,22,5,75,65,80};
int max = stock.maxProfit(prices, prices.length);
System.out.println(max);
}
}