题目原文地址
http://www.programfan.com/club/showbbs.asp?id=126227
一、按要求编写以下函数。
功能: 将给定缓冲区中的#字符移到字符串尾部
函数名称:changetotail
入口参数:psztext指向字符缓冲区的指针,以0结尾。
出口: psztext所指缓冲区中的#字符被移到缓冲区尾部
返回值: 在出口缓冲区中第一个#的位置,若缓冲区中无#字符则返回 -1
说明: 如传入("#W#W#W#WW#") 则传出时应转换为"WWWWW#####"并且返回值为 5
如传入("1#2#3#") 则传出时应转换为"123###"并且返回值为 3
// 1
#include <stdio.h>
int changetotail(char *psztext)
{
const char *p = psztext;
char *p2 = psztext;
int ret;
if (p == NULL)
return -1;
while(*p2 = *p++)
*p2 != '#' && p2++;
ret = p2 == --p ? -1 : p2 - psztext;
while(p2 < p)
*p2++ = '#';
return ret;
}
int main()
{
int i;
char s[][16] =
{
"asdf#@",
"#@",
"###",
"",
"#D#D#D#D",
"D#D#D#D#D",
"#D#D#D#D#",
"D#D#D#D",
"######DDDD",
"DDDD######",
};
for (i = 0; i < 10; i ++)
{
printf("Case %d\n%s\n", i, s[i]);
printf("%s\n%d\n", s[i], changetotail(s[i]));
}
return 0;
}
第2题
二、任给 1<=n<=20 个不同的非零正整数,每个正整数最多使用1次,请问这n个正整数能够加和的结果共有多少种(不考虑和超出long的最大值的可以),
程序中请实现如下函数。用于计算数组data,中ncount的加和的数量。
long getsumcount(long data[], long count);
程序中可以出现别的辅助函数。或辅助结构等。
例如,
data[] = {1,2,3,4};
ncount = 4;
函数返回 10
分解如下。(0不算)
1 = 1
2 = 2
3 = 3 = 1+2
4 = 4 = 1+3
5 = 2+3 = 1+4
6 = 2+4 = 1+2+3
7 = 3+4 = 1+2+4
8 = 1+3+4
9 = 2+3+4
10 = 1+2+3+4
如上。所以结果是10种可能。
我的方法基本思想是把已经出现过的数字用一个位1来标记。避免做对一个数字是否存在的查找操作。
但long范围内要把所有的位都存下来,需要内存太大。2^32/8 byte = 512 MB
所以改为分段保存,连续的32768位存在一起。对连续32768个数字都没有出现过的情况则不记录这块数据
下面是我的程序:
#include <vector>
#include <algorithm>
using namespace std;
class Set
{
typedef unsigned long Int;
struct bitSet // 存32768位
{
Int base; // 一个bitSet保留从base位开始的32768位标记
Int buf[1024]; // 32*1024=32768位,这个大小其实是随意设的
bitSet(Int b):base(b)
{
memset(buf, 0, sizeof(buf));
}
void set(Int n)
{
Int d = n - base;
buf[d>>5] |= 1 << (d & 0x1f); // 对第n位置位
}
bool test(Int n) const
{
Int d = n - base;
return (buf[d>>5] & (1 << (d & 0x1f))) != 0; // 判断第n位。
}
struct Ptr // 这个是为了堆排序不用排bitSet对象(bitSet的体积比较大),排Ptr对象其实就是指针排序
{
Ptr(bitSet *pp = NULL):p(pp){}
bool operator < (const Ptr &o) const // 提供对bitSet的排序关系
{
return p->base < o.p->base;
}
bitSet *p;
};
};
public:
~Set()
{
for (vector< bitSet::Ptr >::iterator b = bits.begin(); b != bits.end(); b++)
delete b->p; // 不要忘了释放空间
}
void add(Int n)
{
bitSet::Ptr bs = find(n);
if (bs.p == NULL) // 如果整个bitSet块都不存在,那么得添加一个新的块了
{
Int base = n & ~0x7fff;
bs.p = new bitSet(base);
bits.push_back(bs);
push_heap(bits.begin(), bits.end());
}
if (!bs.p->test(n)) // 如果这个位已经标记过,那么不应该添加到values内
{
bs.p->set(n);
values.push_back(n);
}
}
bool test(Int n)
{
bitSet::Ptr bs = find(n);
if (bs.p == NULL)
return false;
return bs.p->test(n);
}
const vector< Int > &getValues() const {return values;}
protected:
bitSet::Ptr find(Int n) const
{
typedef vector< bitSet::Ptr >::size_type size_t;
Int base = n & ~0x7fff;
size_t d = 0;
const size_t size = bits.size();
vector< bitSet::Ptr >::const_iterator b = bits.begin(), e = bits.end();
while(d < size && b[d].p->base != base) // 最大堆查找算法。本来想stl内找,貌似没有,就人肉做一个了
{
if (b[d].p->base < base)
d = d*2 + 1;
else
d = (d+1)*2;
}
if (d >= size)
return bitSet::Ptr(); // 找不到返回NULL指针对象
return b[d];
}
vector< bitSet::Ptr > bits;
vector< Int > values;
};
long getsumcount(long data[], long count)
{
Set set;
set.add(0); // 初始得有个0,便于下面代码统一
for (int i = 0; i < count; i++)
{
vector< Set::Int >::const_iterator n;
vector< Set::Int > newInt;
const vector< Set::Int > &v = set.getValues();
for (n = v.begin(); n != v.end(); n++)
{
if (!set.test(*n + data[i])) // 对每个数字,如果加新数字的和不在集合内,那么准备添加到集合内
newInt.push_back(*n + data[i]);// 之所以这里不直接添加到set内,是因为v就是set内的values,如果这里对set的values做增加元素,将导致迭代器n失效。
}
for (n = newInt.begin(); n != newInt.end(); n++)
{
set.add(*n); // 把新的元素添加进去。
}
}
return set.getValues().size() - 1; // 最后去掉元素0
}
int main()
{
long data[] =
{
0x1,0x2,0x4,0x8,
0x10,0x20,0x40,0x80,
0x100,0x200,0x400,0x800,
0x1000,0x2000,0x4000,0x8000,
0x10000,0x20000,0x40000,0x80000,
};
printf("%d\n", getsumcount(data, 20));
return 0;
}