编写反转字符串的程序,要求优化速度、优化空间
2011-09-11 16:04
357 查看
这是网络流传的Microsoft的面试题目之一:“编写反转字符串的程序,要求优化速度、优化空间”。
因为最近一直很多关注算法方面的实践和研究,因此对这个问题进行了一些思考,给出了5种实现方法(有两种解法相关性比较大)。这是网络流传的Microsoft的面试题目之一:“编写反转字符串的程序,要求优化速度、优化空间”。因为最近一直很多关注算法方面的实践和研究,因此对这个问题进行了一些思考,给出了5种实现方法(有两种解法相关性比较大)。
解法一:第一次看到这题目,想到最简单、最直觉的解法就是:遍历字符串,将第一个字符和最后一个交换,第二个和倒数第二个交换,依次循环,即可,于是有了第一个解法:
char* strrev1(const char* str)
{
int len = strlen(str);
char* tmp = new char[len + 1];
strcpy(tmp,str);
for (int i = 0; i < len/2; ++i)
{
char c = tmp;
tmp = tmp[len-i-1];
tmp[len-i-1] = c;
}
return tmp;
}
这里是通过数组的下标方式访问字符串的字符,实际上用指针直接操作即可。
解法二正是基于此,实现代码为:
char* strrev2(const char* str)
{
char* tmp = new char[strlen(str) + 1];
strcpy(tmp,str);
char* ret = tmp;
char* p = tmp + strlen(str) - 1;
while (p > tmp)
{
char t = *tmp;
*tmp = *p;
*p = t;
--p;
++tmp;
}
return ret;
}
显然上面的两个解法中没有考虑时间和空间的优化,一个典型的优化策略就是两个字符交换的算法优化,我们可以完全不使用任何外部变量即完成两个字符(或者整数)的交换,这也是一个很经典的面试题目。特别是一些嵌入式硬件相关编程中经常要考虑寄存器的使用,因此经常有不使用任何第三个寄存器即完成两个寄存器数据的交换的题目。一般有两个解法,对应这里的解法三和解法四。
解法三的实现代码为:
char* strrev3(const char* str)
{
char* tmp = new char[strlen(str) + 1];
strcpy(tmp,str);
char* ret = tmp;
char* p = tmp + strlen(str) - 1;
while (p > tmp)
{
*p ^= *tmp;
*tmp ^= *p;
*p ^= *tmp;
--p;
++tmp;
}
return ret;
}
解法四的实现代码为:
char* strrev4(const char* str)
{
char* tmp = new char[strlen(str) + 1];
strcpy(tmp,str);
char* ret = tmp;
char* p = tmp + strlen(str) - 1;
while (p > tmp)
{
*p = *p + *tmp;
*tmp = *p - *tmp;
*p = *p - *tmp;
--p;
++tmp;
}
return ret;
}
实际上我们还可以通过递归的思想来解决这个问题,思想很简单:每次交换首尾两个字符,中间部分则又变为和原来字符串同样的问题,因此可以通过递归的思想来解决这个问题,对应解法五的实现代码为:
char* strrev5(/*const */char* str,int len)
{
if (len <= 1)
return str;
char t = *str;
*str = *(str + len -1);
*(str + len -1) = t;
return (strrev5(str + 1,len - 2)-1);
}
以下给出一个测试程序:
int main(int argc,char* argv[])
{
char* str = "hello";
printf(str);
printf("\n");
char* str2 = strrev1(str);
printf(str2);
printf("\n");
char* str3 = strrev2(str2);
printf(str3);
printf("\n");
char* str4 = strrev3(str3);
printf(str4);
printf("\n");
char* str5 = strrev4(str4);
printf(str5);
printf("\n");
char* str6 = strrev5(str5,strlen(str5));
printf(str6);
printf("\n");
return 0;
}
你就可以看到字符串"hello"和"olleh"交替输出了。
说明:1)这里解法中没有认真考虑输入字符串的合法性和特殊长度(如NULL、一个字符等)字符串的处理;2)前4个算法不改变输入字符串的值,解法五修改了输入字符串。
因为最近一直很多关注算法方面的实践和研究,因此对这个问题进行了一些思考,给出了5种实现方法(有两种解法相关性比较大)。这是网络流传的Microsoft的面试题目之一:“编写反转字符串的程序,要求优化速度、优化空间”。因为最近一直很多关注算法方面的实践和研究,因此对这个问题进行了一些思考,给出了5种实现方法(有两种解法相关性比较大)。
解法一:第一次看到这题目,想到最简单、最直觉的解法就是:遍历字符串,将第一个字符和最后一个交换,第二个和倒数第二个交换,依次循环,即可,于是有了第一个解法:
char* strrev1(const char* str)
{
int len = strlen(str);
char* tmp = new char[len + 1];
strcpy(tmp,str);
for (int i = 0; i < len/2; ++i)
{
char c = tmp;
tmp = tmp[len-i-1];
tmp[len-i-1] = c;
}
return tmp;
}
这里是通过数组的下标方式访问字符串的字符,实际上用指针直接操作即可。
解法二正是基于此,实现代码为:
char* strrev2(const char* str)
{
char* tmp = new char[strlen(str) + 1];
strcpy(tmp,str);
char* ret = tmp;
char* p = tmp + strlen(str) - 1;
while (p > tmp)
{
char t = *tmp;
*tmp = *p;
*p = t;
--p;
++tmp;
}
return ret;
}
显然上面的两个解法中没有考虑时间和空间的优化,一个典型的优化策略就是两个字符交换的算法优化,我们可以完全不使用任何外部变量即完成两个字符(或者整数)的交换,这也是一个很经典的面试题目。特别是一些嵌入式硬件相关编程中经常要考虑寄存器的使用,因此经常有不使用任何第三个寄存器即完成两个寄存器数据的交换的题目。一般有两个解法,对应这里的解法三和解法四。
解法三的实现代码为:
char* strrev3(const char* str)
{
char* tmp = new char[strlen(str) + 1];
strcpy(tmp,str);
char* ret = tmp;
char* p = tmp + strlen(str) - 1;
while (p > tmp)
{
*p ^= *tmp;
*tmp ^= *p;
*p ^= *tmp;
--p;
++tmp;
}
return ret;
}
解法四的实现代码为:
char* strrev4(const char* str)
{
char* tmp = new char[strlen(str) + 1];
strcpy(tmp,str);
char* ret = tmp;
char* p = tmp + strlen(str) - 1;
while (p > tmp)
{
*p = *p + *tmp;
*tmp = *p - *tmp;
*p = *p - *tmp;
--p;
++tmp;
}
return ret;
}
实际上我们还可以通过递归的思想来解决这个问题,思想很简单:每次交换首尾两个字符,中间部分则又变为和原来字符串同样的问题,因此可以通过递归的思想来解决这个问题,对应解法五的实现代码为:
char* strrev5(/*const */char* str,int len)
{
if (len <= 1)
return str;
char t = *str;
*str = *(str + len -1);
*(str + len -1) = t;
return (strrev5(str + 1,len - 2)-1);
}
以下给出一个测试程序:
int main(int argc,char* argv[])
{
char* str = "hello";
printf(str);
printf("\n");
char* str2 = strrev1(str);
printf(str2);
printf("\n");
char* str3 = strrev2(str2);
printf(str3);
printf("\n");
char* str4 = strrev3(str3);
printf(str4);
printf("\n");
char* str5 = strrev4(str4);
printf(str5);
printf("\n");
char* str6 = strrev5(str5,strlen(str5));
printf(str6);
printf("\n");
return 0;
}
你就可以看到字符串"hello"和"olleh"交替输出了。
说明:1)这里解法中没有认真考虑输入字符串的合法性和特殊长度(如NULL、一个字符等)字符串的处理;2)前4个算法不改变输入字符串的值,解法五修改了输入字符串。
相关文章推荐
- 编写反转字符串的程序,要求优化速度、优化空间。
- 编写反转字符串的程序,要求优化速度、优化空间
- 每天三道冲刺工作--编写反转字符串的程序,要求优化速度、优化空间。
- 编写反转字符串的程序,要求优化速度、优化空间。
- 反转字符串,优化速度,优化空间。
- 编写高质量代码改善C#程序的157个建议[为类型输出格式化字符串、实现浅拷贝和深拷贝、用dynamic来优化反射]
- 汇编语言: 试编写一段程序,要求比较两个字符串 string1 和 string2 所含字符是否相等,如相 等则显示“MATCH”, 若不相同则显示“NO MATCH”。
- 要求:不申请变量和空间 反转字符串 ,用一个函数实现。 异或^交换或者加减交换的典型应用! VIA 笔试题
- 汇编语言: 试编写一段程序,要求输入两个字符串,如两个字符串相等则显示“MATCH”, 否则 显示“NO MATCH”。
- 编写一个程序,输入一串不超过60个字符组成的且不包含换行符的字符串,将字符串中的A到Z的字母按英文字典字母顺序重新排列,排列后的单词的长度要与原始句子中的长度相同,并且要求只对A到Z的字母重新排列,其
- 要求:不申请变量和空间反转字符串,用一个函数实现。VIA笔试题
- (1)写一个程序,用于分析一个字符串中各个单词出现的频率,并将单词和它出现的频率输出显示。(单词之间用空格隔开,如“Hello World My First Unit Test”); (2)编写单元测试进行测试; (3)用ElcEmma查看代码覆盖率,要求覆盖率达到100%。
- 使用C/C++编写函数,实现字符串反转,要求不使用任何系统函数,且时间复杂度最小
- 编写一个程序,将两个字符串链接起来,结果取代第一个字符串。要求用方法
- 要求编写程序,读入5个字符串,按由小到大的顺序输出。 (2)功能要求 ①输入格式:输入为由空格分隔的5个非空字符串,每个字符串不包括空格、制表符、换行符等空白字符,长度小于80。
- S是一个存放在数组中,长为n的字符串,试编写一个程序将S按下述要求改造后输出
- 编写高质量代码改善C#程序的157个建议[为类型输出格式化字符串、实现浅拷贝和深拷贝、用dynamic来优化反射]
- 汇编程序:已知有一字符串STR,以'$'为结束标志,编写程序,把STR的内容复 制到NEW_STR中? 要求复制时(1)滤去所有非英文字符;(2)把大写字母变成小写;(3)统计新字符的长度放在NUM中
- 以单词为单位反转字符串,要求不申请任何空间
- 找到一个字符串,优化速度,优化空间