第一題:有一個字符數組的內容爲:“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;
}
總結
當思考問題時,不能眼高手低全憑腦子想,而不屑於動手。越是沒思路或者想不明白的問題,越要多在紙上畫畫,靈感往往來源於這個邊想邊寫邊畫的過程。