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