字符串的逆置和旋轉問題

第一題:有一個字符數組的內容爲:“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;
}

總結
當思考問題時,不能眼高手低全憑腦子想,而不屑於動手。越是沒思路或者想不明白的問題,越要多在紙上畫畫,靈感往往來源於這個邊想邊寫邊畫的過程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章