字符串的逆置和旋转问题

第一题:有一个字符数组的内容为:“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;
}

总结
当思考问题时,不能眼高手低全凭脑子想,而不屑于动手。越是没思路或者想不明白的问题,越要多在纸上画画,灵感往往来源于这个边想边写边画的过程。

发布了50 篇原创文章 · 获赞 30 · 访问量 9178

猜你喜欢

转载自blog.csdn.net/qq_42913794/article/details/90082448
今日推荐