不申请变量和空间反转字符串
2009-09-17 20:51
323 查看
不申请变量和空间反转字符串
要求:不申请变量和空间反转字符串,用一个函数实现。VIA笔试题
基本思路:从两头往中间做字符交换。字符串最后一个字符是'/0',表示结束,没有实际意义,可以将它当作中间变量,等处理完成后,再将最后一个字符置'/0'即可
***********************************************************************
void Reverse (char *s)
{
if(strlen(s) == 1) // 当为一个字符时无需交换或奇数个
return;
if(*(s)) // 0个或偶数个
{
*s = *s + *(s+strlen(s)-1);
*(s+strlen(s)-1) = *s - *(s+strlen(s)-1);
*s = *s - *(s+strlen(s)-1);
// 实现字符串首末字符互换,但加法可能会溢出
*(unsigned short*)(s+strlen(s)-1) = (*(s+strlen(s)-1))<<8;
// 把字符串的最后一个字节往后移了一位,利用了0 = ‘/0’
// 当然也可以利用上面交换字符的方法,不过移位利用了0 = ‘/0’的效率更高
// 上面四步的本质是实现三个数两两互换,最简单的是两次两两互换
// 但是目前结尾符是已知的,直接把第一个放到结尾处,最后一个放第一个,将
// 最后一个用结尾符填上即可,只需三步,易于理解,前提是有变量保存字符串的//长度
// 但是由于不能申请临时变量,移动了结尾符号后,strlen函数就不能用了
// 因此上述强制转换的方式是唯一的
// 然后将去掉了首尾字符的新串传进去,递归调用
Reverse (s+1);
*(unsigned short*)(s+strlen(s)) = *(s+strlen(s)+1);
// 将‘/0’逐步后移,还原更改后的子串
}
else
return;
}
图示过程:字符串abcdef
S+1 = Str = abcdef’/0’ abcdef’/0’ > fbcdea’/0’ > fbcde’/0’a
S+1 = Str = bcde’/0 fbcde’/0’a > fecdb’/0’a > fecd’/0’ba
S+1 = Str = cd’/0’ fecd’/0’ba > fedc’/0’ba > fed’/0’cba
S+1 = Str =’/0’ ,递归返回,此时s= cd’/0’ 已经在上一步改为 d’/0’c > dc’/0’ > edcb’/0’ > fedcba’/0’
考虑串的长度为奇数的情况,当为奇数时,最后传进去的串长度为1,此时无需交互,应该直接退出。因此在入口处补上判断奇偶的条件
if(strlen(s) == 1)
return;
当然也可以在递归调用前判断改动后的字符串长度if( strlen(str+ 1) >= 2 )时,才调用,可以消除奇数的影响
当原始字符串为一个时,第一次就应该无任何处理的,所以在入口处判断更合理哦
×××××××××××××××××××××××××××××××
优化,不申请任何变量,支持链式操作,返回char *
char * Reverse (char *s)
{
if(strlen(s) == 1)
return s;
if(*(s))
{
*s = *s + *(s+strlen(s)-1);
*(s+strlen(s)-1) = *s - *(s+strlen(s)-1);
*s = *s - *(s+strlen(s)-1);
// 实现字符串首末字符互换,但加法可能会溢出
*(unsigned short*)(s+strlen(s)-1) = (*(s+strlen(s)-1))<<8;
Reverse (s+1);
*(unsigned short*)(s+strlen(s)) = *(s+strlen(s)+1);
}
return s; // 此句没有,程序就错了,因为递归的最外层是进入if(*(s))的,此时无返回值
}
×××××××××××××××××××××××××××××××
申请了一个变量保存串的长度,一般面试这个程序就可以了,能写出这个其实已经很牛b了,整上面那个,估计别人开始怀疑是以前做过这个题目了,呵呵,还得装傻点
char * Reverse (char *s)
{
if(strlen(s) == 1)
return s;
if(*(s))
{
int len = strlen(s);
*(s+len) = *s;
*s = *(s+len-1);
*(s+len-1) = '/0';
// 首尾字符及结束符交换位置
// 去掉首尾字符后再递归调用
Reverse (s+1);
//*(unsigned short*)(s+strlen(s)) = *(s+strlen(s)+1);
*(s+len-1) = *(s+len);
*(s+len) = '/0'; // 恢复原来改变后的串
}
return s;
}
×××××××××××××××××××××××××××××××
将字符串的最后一个元素递归移动到队头,递归到达尾部,异或^交换,队尾元素前移一格,返回上层,再次交换,最后即将队尾移到队头
void tail2head(char* s)
{
if(strlen(s)==1)
{
return;
}
else if(strlen(s)==2)
{
s[0] = s[1]^s[0];
s[1] = s[1]^s[0];
s[0] = s[1]^s[0];
return;
}
else if(strlen(s)>2)
{
tail2head(s+1);
s[0] = s[1]^s[0];
s[1] = s[1]^s[0];
s[0] = s[1]^s[0];
}
}
递归一次移动队尾至队头,更新队头至下一个元素,再次调用tail2head,最后即可全部逆序
char* Reverse(char *s)
{
if(strlen(s)>1)
{
tail2head(s);
Reverse(s+1);
}
return s;
}
此法元素移动次数最多,但是思路比较清晰,另外整个功能用了两个递归函数实现,打破了通常只有一个接口函数的固定思维
main()
{
char streven[10] = "abcdef";
char strood[10] = "1234567";
char strone[10] = "1";
char strtwo[10] = "12";
printf("string 'abcdef' reversed is '%s'/n",Reverse(streven));
printf("string '1234567' reversed is '%s'/n",Reverse(strood));
printf("string '1' reversed is '%s'/n",Reverse(strone));
printf("string '12' reversed is '%s'/n",Reverse(strtwo));
return 0;
//string 'abcdef' reversed is 'fedcba'
//string '1234567' reversed is '765123?' 当串的长度为奇数时好像还有点问题
//string '1234567' reversed is '7654321' 补充了判断条件后无误
//string '1' reversed is '1'
//string '12' reversed is '21'
}
要求:不申请变量和空间反转字符串,用一个函数实现。VIA笔试题
基本思路:从两头往中间做字符交换。字符串最后一个字符是'/0',表示结束,没有实际意义,可以将它当作中间变量,等处理完成后,再将最后一个字符置'/0'即可
***********************************************************************
void Reverse (char *s)
{
if(strlen(s) == 1) // 当为一个字符时无需交换或奇数个
return;
if(*(s)) // 0个或偶数个
{
*s = *s + *(s+strlen(s)-1);
*(s+strlen(s)-1) = *s - *(s+strlen(s)-1);
*s = *s - *(s+strlen(s)-1);
// 实现字符串首末字符互换,但加法可能会溢出
*(unsigned short*)(s+strlen(s)-1) = (*(s+strlen(s)-1))<<8;
// 把字符串的最后一个字节往后移了一位,利用了0 = ‘/0’
// 当然也可以利用上面交换字符的方法,不过移位利用了0 = ‘/0’的效率更高
// 上面四步的本质是实现三个数两两互换,最简单的是两次两两互换
// 但是目前结尾符是已知的,直接把第一个放到结尾处,最后一个放第一个,将
// 最后一个用结尾符填上即可,只需三步,易于理解,前提是有变量保存字符串的//长度
// 但是由于不能申请临时变量,移动了结尾符号后,strlen函数就不能用了
// 因此上述强制转换的方式是唯一的
// 然后将去掉了首尾字符的新串传进去,递归调用
Reverse (s+1);
*(unsigned short*)(s+strlen(s)) = *(s+strlen(s)+1);
// 将‘/0’逐步后移,还原更改后的子串
}
else
return;
}
图示过程:字符串abcdef
S+1 = Str = abcdef’/0’ abcdef’/0’ > fbcdea’/0’ > fbcde’/0’a
S+1 = Str = bcde’/0 fbcde’/0’a > fecdb’/0’a > fecd’/0’ba
S+1 = Str = cd’/0’ fecd’/0’ba > fedc’/0’ba > fed’/0’cba
S+1 = Str =’/0’ ,递归返回,此时s= cd’/0’ 已经在上一步改为 d’/0’c > dc’/0’ > edcb’/0’ > fedcba’/0’
考虑串的长度为奇数的情况,当为奇数时,最后传进去的串长度为1,此时无需交互,应该直接退出。因此在入口处补上判断奇偶的条件
if(strlen(s) == 1)
return;
当然也可以在递归调用前判断改动后的字符串长度if( strlen(str+ 1) >= 2 )时,才调用,可以消除奇数的影响
当原始字符串为一个时,第一次就应该无任何处理的,所以在入口处判断更合理哦
×××××××××××××××××××××××××××××××
优化,不申请任何变量,支持链式操作,返回char *
char * Reverse (char *s)
{
if(strlen(s) == 1)
return s;
if(*(s))
{
*s = *s + *(s+strlen(s)-1);
*(s+strlen(s)-1) = *s - *(s+strlen(s)-1);
*s = *s - *(s+strlen(s)-1);
// 实现字符串首末字符互换,但加法可能会溢出
*(unsigned short*)(s+strlen(s)-1) = (*(s+strlen(s)-1))<<8;
Reverse (s+1);
*(unsigned short*)(s+strlen(s)) = *(s+strlen(s)+1);
}
return s; // 此句没有,程序就错了,因为递归的最外层是进入if(*(s))的,此时无返回值
}
×××××××××××××××××××××××××××××××
申请了一个变量保存串的长度,一般面试这个程序就可以了,能写出这个其实已经很牛b了,整上面那个,估计别人开始怀疑是以前做过这个题目了,呵呵,还得装傻点
char * Reverse (char *s)
{
if(strlen(s) == 1)
return s;
if(*(s))
{
int len = strlen(s);
*(s+len) = *s;
*s = *(s+len-1);
*(s+len-1) = '/0';
// 首尾字符及结束符交换位置
// 去掉首尾字符后再递归调用
Reverse (s+1);
//*(unsigned short*)(s+strlen(s)) = *(s+strlen(s)+1);
*(s+len-1) = *(s+len);
*(s+len) = '/0'; // 恢复原来改变后的串
}
return s;
}
×××××××××××××××××××××××××××××××
将字符串的最后一个元素递归移动到队头,递归到达尾部,异或^交换,队尾元素前移一格,返回上层,再次交换,最后即将队尾移到队头
void tail2head(char* s)
{
if(strlen(s)==1)
{
return;
}
else if(strlen(s)==2)
{
s[0] = s[1]^s[0];
s[1] = s[1]^s[0];
s[0] = s[1]^s[0];
return;
}
else if(strlen(s)>2)
{
tail2head(s+1);
s[0] = s[1]^s[0];
s[1] = s[1]^s[0];
s[0] = s[1]^s[0];
}
}
递归一次移动队尾至队头,更新队头至下一个元素,再次调用tail2head,最后即可全部逆序
char* Reverse(char *s)
{
if(strlen(s)>1)
{
tail2head(s);
Reverse(s+1);
}
return s;
}
此法元素移动次数最多,但是思路比较清晰,另外整个功能用了两个递归函数实现,打破了通常只有一个接口函数的固定思维
main()
{
char streven[10] = "abcdef";
char strood[10] = "1234567";
char strone[10] = "1";
char strtwo[10] = "12";
printf("string 'abcdef' reversed is '%s'/n",Reverse(streven));
printf("string '1234567' reversed is '%s'/n",Reverse(strood));
printf("string '1' reversed is '%s'/n",Reverse(strone));
printf("string '12' reversed is '%s'/n",Reverse(strtwo));
return 0;
//string 'abcdef' reversed is 'fedcba'
//string '1234567' reversed is '765123?' 当串的长度为奇数时好像还有点问题
//string '1234567' reversed is '7654321' 补充了判断条件后无误
//string '1' reversed is '1'
//string '12' reversed is '21'
}
相关文章推荐
- C/C++面试之算法系列--不申请变量和空间反转字符串
- 要求:不申请变量和空间 反转字符串 ,用一个函数实现。 异或^交换或者加减交换的典型应用! VIA 笔试题
- 要求:不申请变量和空间反转字符串,用一个函数实现。VIA笔试题
- 不申请变量和空间反转字符串
- 以单词为单位反转字符串,要求不申请任何空间
- 不申请新的空间,字符串反转
- 内存空间的申请,变量之间是不相互影响的。
- 把一个字符串的大写字母放到字符串的后面 ,各个字符的相对位置不变,不能申请额外的空间
- 两个整形变量的互换;以及在不申请空间的情况下实现互换;十个数中求最大值
- 字符移位 小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。 你能帮帮小Q吗? 输入描述: 输入数据有多组
- 循环左移字符串,不申请内存空间
- java学习001 Java与c中定义变量申请空间的理解
- 编写反转字符串的程序,要求优化速度、优化空间。
- 不申请额外空间调整字符串大小写顺序,大写字母依次放到后面
- 把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,不能申请额外的空间。
- 设计算法并写出代码移除字符串中重复的字符,不能使用额外的缓存空间。注意: 可以使用额外的一个或两个变量,但不允许额外再开一个数组拷贝。
- 把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,不能申请额外的空间
- 腾讯2017年实习生编程题目(第二题)----2.算法基础-字符移位 小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。
- 【C编程练习】华为2013校园招聘机试题3:对源字符串中得字符串进行查找替换并返回动态申请空间的指针char* Fun(char*pSrc,char*pOldStr, char*pNewStr)
- 小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。 你能帮帮小Q吗?