第一题:有一个字符数组的内容为:“student a am i”,请将数组的内容改为:“i am a student”, 要求:不能使用库函数,只能开辟有限个空间(空间个数和字符串的长度无关)
那么这个题想把这4个单词逆置,但是我们会发现直接从逆置单词入手会有困难。在字符串的逆置方面我们比较熟悉的是对整个字符串的逆置,那么我的思路是:先将整个字符串逆置,再将每个单词逆置。(逆置单词就是当指针指向的字符为‘ ’时,则证明找到了一个单词)
即:student a am i
i ma a tneduts
i am a student
C代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<math.h>
void Reverse_Swap(char *start,char *end)
{
assert(start!=NULL);
assert(end != NULL);
while (start < end)
{
char tmp = *start;
*start = *end;
*end = tmp;
start++;
end--;
}
}
void Reverse_Array(char *arr, int len)
{
char *p = arr;
while (*p)
{
char *start= p;
while ((*p != ' ')&&(*p != '\0'))
{
p++;
}
Reverse_Swap(start,p-1);
if (*p == ' ')//当找到一个单词时,要使指针指向下一个不为‘ ’的字符
{
p++;
}
}
}
int main()
{
char arr[] = "student a am I";
int len =sizeof(arr)/sizeof(arr[0])-1;
char *left = arr;
char *right =arr+len - 1;
Reverse_Swap(left, right);
printf("%s\n", arr);
Reverse_Array(arr,len);
printf("%s\n", arr);
system("pause");
return 0;
}
第二题1.实现一个函数,可以左旋字符串中的k个字符。
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
这个题目首先看到肯定会想起字符移动向前移动k位算法,暴力的算法。即用指针指向第一个元素,将要往后移动的字符先放在临时变量tmp里,将剩下的字符一次往前移动k次,最后再按顺序将tmp里的字符依次放入空缺的位置即可。
实现函数:
void left_move1(char *str, int k)
{
if (k<0 || k>strlen(str))
{
printf("不合法\n");
return;
}
while (k)
{
char *cur = str;
char tmp = *cur;
while (*(cur + 1))
{
*cur = *(cur + 1);
cur++;
}
*cur = tmp;
k--;
}
}
但当你拿笔写写画画时,常常会有不一样的思路,那么这个问题我想到的思路是:以要旋转的第k个字符为界,将要旋转的k个字符分为一组,剩下的分为一组,分别将这两组字符逆置,最后再将整个字符数组逆置输出,惊喜地发现就能得到目的字符数组了。
C代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//交换函数
void Reverse(char *left, char *right)
{
assert(left != NULL && right != NULL);
while (left < right)
{
char tmp = 0;
tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
//实现功能的函数
void Left_handed(char *arr, int k, int len)//
{
if (k<0 || k>strlen(arr))
{
printf("不合法\n");
return 0;
}
int i = 0;
char *p = arr;
while (i < k)
{
p = arr + i;
i++;
}
Reverse(arr, p);//逆置k个字符之前的字符数组
Reverse(p + 1, arr + len - 1);//逆置k个字符之后的字符数组
Reverse(arr, arr + len - 1);//逆置整个数组
}
int main()
{
int k = 0;
char arr[] = "ABCDE";
int len = sizeof(arr) / sizeof(arr[0]) - 1;
scanf("%d", &k);
Left_handed(arr, k, len);
/*left_move1(arr, k);*/
printf("%s", arr);
system("pause");
return 0;
}
3.2.判断一个字符串是否为另外一个字符串旋转之后的字符串。
例如:给定s1 =AABCD和s2 = BCDAA,返回1
给定s1=abcd和s2=ACBD,返回0.
AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA
AABCD右旋一个字符得到DAABC
这个题目实际上就是一个比较字符串的问题,我的思路是现将得到的字符数组复制一份,衔接在一起再在里面找是否有旋转的这个字符数组,如果有,那么前者就是由后者旋转得到的。
例如判断AABCD是否能旋转得到ABCDA,则先得到ABCDAABCDA,然后在里面找ABCDA找到了则说明能得到,找不到则说明不能得到。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 10
void Merge_string(char *arr)
{
int i = 0;
for (i = 0; i < N - 5; i++)
{
arr[i + 5] = arr[i];
}
}
int Judge_string(char *arr1, char *arr2)
{
Merge_string(arr1);
char *p = arr1;
char arr3[6];
int i = 0;
int j = 0;
while (*p != *arr2)
{
p++;
}
for (i = 0; i < 5; i++)
{
arr3[i] = *p;
p++;
}
arr3[i] = '\0';
//printf("%s", arr3);
for (j = 0; j < i; j++)
if (strcmp(arr3, arr2) == 0)
return 1;
else
return 0;
}
int main()
{
char arr1[N + 1] = "ABCDE";
char arr2[N] = "CDEAB";
int result = 0;
result = Judge_string(arr1, arr2);
if (result)
{
printf("yes\n");
}
else
{
printf("No\n");
}
system("pause");
return 0;
}
但是上面的程序算法过于冗杂,很多功能都可以通过函数来实现。
那么实现的函数可以改成这样:
void Merge_string(char *arr)
{
arr = strncat(arr, arr, strlen(arr));
printf("%s\n", arr);
}
int Judge_string(char *arr1, char *arr2)
{
Merge_string(arr1);
if (strstr(arr1, arr2) != NULL)
{
return 1;
}
else
return 0;
}
总结
当思考问题时,不能眼高手低全凭脑子想,而不屑于动手。越是没思路或者想不明白的问题,越要多在纸上画画,灵感往往来源于这个边想边写边画的过程。