《C++ Primer 第五版》书实在是太长,太厚了。总是看了十几页就看累了,坚持不了多久,想了想还是别勉强自己,决定把它当工具书查看,或者积累足够的C++经验后再翻阅一遍。
目前的打算是结合一本叫《Craking the coding interview》里的例子来学,选这个的原因是 fanfanK http://blog.csdn.net/fanfank?viewmode=contents 的推荐,同时这本书又有hawstein http://hawstein.com/posts/ctci-solutions-contents.html 提供很好的解答环境,打算每天做3题。
10.8
作者:Hawstein
出处:http://hawstein.com/posts/1.1.html
声明:本文采用以下协议进行授权: 自由转载-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0 ,转载请注明作者及出处。
Q1.1: http://hawstein.com/posts/1.1.html
实现一个算法来判断一个字符串中的字符是否唯一(即没有重复).不能使用额外的数据结构。 (即只使用基本的数据结构)
方法一采用了一个bool数组来记录是否出现过,方法的特点主要是结合Ascii码可以转换为数字,对应记录到数组中。
方法二把数组记录变为了一个长度为8的int 数组a,然后进行位运算,8*4*8=256,
看这个方法二的时候 顺便学习了下《C++ Primer 第五版》里的4.8 位运算符的部分。其中P137中写道:常见的错误是把位运算符和逻辑运算符搞混了。这也的确是我犯过的错误,比如位或| 和逻辑或|| 搞混过。
P126:“关系运算符作用于算数类型或指针类型,逻辑运算符作用于任意能转换成布尔值的类型。逻辑运算符和关系运算符的返回值都是布尔类型”
个人感想:用bool数组和位来记录一些0,1数据,的确很节省,顺便复习了下运算符。
Q1.2 http://hawstein.com/posts/1.2.html
写代码翻转一个C风格的字符串。(C风格的意思是"abcd"需要用5个字符来表示,包含末尾的 结束字符)
方法一用的是用两个指针去分别指头和尾,然后用逐个交换,其中的交换函数是这么写的:
void swap(char &a, char &b)
{
a=a^b;
b=a^b;
a=a^b;
}
用的是引用传递,同时类似的交换方法有:
void swap(int &a, int &b)
{
b=a-b;
a=a-b;
b=a+b;
}
这里会有一个小的bug,就是:如果swap这个函数里两个形参引用的是同一个变量,那么这两种方法都会出问题,存在这种情况的时候,还是用临时变量比较好。
这里顺便完成了Q19.1:写一个函数交换两个数,不能使用临时变量。 http://hawstein.com/posts/19.1html
方法二就是常规思路了,直接用int n=strlen(s) 来获取字符串长度,然后逐个交换即可。
个人感想:字符串用指针来处理,交换两个数时,可能存在bug。
Q1.3:
设计算法并写出代码移除字符串中重复的字符,不能使用额外的缓存空间。注意: 可以使用额外的一个或两个变量,但不允许额外再开一个数组拷贝。
方法一:就单纯遍历每个元素,访问一个就把字符串结尾的元素中相同的元素去掉(可以置0 或者 ‘\0'),时间复杂度为O(n*n)
void removeDuplicate(char s[])
{
int len = strlen(s);
if(len < 2) return;
int p = 0;
for(int i=0; i < len; ++i)
{
if(s[i] != '\0')
{
s[p++] = s[i];
for(int j=i+1; j < len; ++j)
if(s[j]==s[i])
s[j] = '\0';
}
}
s[p] = '\0';
}
也有另外一种方法是O(kn)的,就是看0~tail之间有没有这个字符,没的话就s[tail++]=s[i],也就是把“处理过的数据”后面再加一个,如果有就跳过,最后做完之后,再加个结尾符号即可。
代码如下(具体分析可参考http://stackoverflow.com/questions/2598129/function-to-remove-duplicate-characters-in-a-string):
void remove(char *str)
{
if (str == NULL) return;
int len = strlen(str);
if (len < 2) return;
int tail = 1;
for (int i = 1; i < len; ++i) {
int j;
for (j = 0; j < tail; ++j) {
if (str[i] == str[j]) break;
}
if (j == tail) {
str[tail++] = str[i];
}
}
str[tail] = 0;
}