【C语言进阶】 杨氏矩阵,字符串左旋,字符串旋转结果题目解析

杨氏矩阵

题目要求:有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。

示例

f137eb3a1283482a845ff5facb200cf1.png

 分析:我们仔细分析,不难发现,对于杨氏矩阵老说,右上角和左下角的元素是有特点的。右上角的元素是一行中最大的,一列中最小的。左下角的元素是一行中最小的,是一列中最大的。所以我们可以从右上角或者左下角开始查找。比如:从右上角开始查找的时候,右上角的元素比我们要查找元素小,我们就可以去掉右上角元素所在的这一行;右上角的元素比我们要查找的元素大,我们就可以去掉右上角元素所在的这一列。然后依然找右上角的元素继续和要查找的元素与比较。这样每一次比较去掉一行或者去掉一列。这个查找效率是高于遍历数组元素的

代码实现:

#include <stdio.h>

int findnum(int a[][3], int x, int y, int f) //第一个参数的类型需要调整
{
	int i = 0, j = y - 1; //从右上角开始遍历
	while (j >= 0 && i < x)
	{
		if (a[i][j] < f) //比我大就向下
		{
			i++;
		}
		else if (a[i][j] > f) //比我小就向左
		{
			j--;
		}
		else
		{
			return 1;
		}
	}
	return 0;
}

int main()
{
	int a[][3] = { {1, 3, 5},
				  {3, 5, 7}, 
				  {5, 7, 9} }; //一个示例

	if (findnum(a, 3, 3, 2))
	{
		printf("It has been found!\n");
	}
	else
	{
		printf("It hasn't been found!\n");
	}

	return 0;
}

字符串左旋

题目要求:

实现一个函数,可以左旋字符串中的k个字符。

例如:

ABCD左旋一个字符得到BCDA

ABCD左旋两个字符得到CDAB

分析:设计循环使其可以旋1次,然后让他执行n次是一个最简单的思路:

33cf06db63a341faa51131b0a6b6e739.png

实现如下:

void leftRound(char * src, int time)
{
	int i, j, tmp;
  int len = strlen(src);
  time %= len; //长度为5的情况下,旋转6、11、16...次相当于1次,7、12、17...次相当于2次,以此类推。
	for (i = 0; i < time; i++) //执行k次的单次平移
	{
		tmp = src[0];
		for(j = 0; j < len - 1; j++) //单次平移
		{
			src[j] = src[j + 1];
		}
		src[j] = tmp;
	}
}

改进一

这个思路当然可以,但是一次一次转毕竟太麻烦,就不能一次到位么?

当然可以,我们可以选择拼接法,一次到位:

 

454e4cdc748e4a5986c1cdcfbc3a90a8.png

 

实现如下: 

void leftRound(char * src, int time)
{
	int len = strlen(src);
	int pos = time % len; //断开位置的下标
	char tmp[256] = { 0 }; //更准确的话可以选择malloc len + 1个字节的空间来做这个tmp
	
	strcpy(tmp, src + pos); //先将后面的全部拷过来
	strncat(tmp, src, pos); //然后将前面几个接上
	strcpy(src, tmp); //最后拷回去
}

改进二:

改进一要用到一个数组形成的辅助空间,让人觉得有点不爽,还可以有更好的选择,例如ABCDEFG,左旋3次后变成DEFGABC,有一个特殊的操作方式:

先将要左旋的前三个家伙逆序(CBADEFG),然后将后半段也逆序(CBAGFED),最后整体逆序(DEFGABC)即可。这样只需要做数值交换即可,可以写一个函数帮我们完成局部逆序,

代码如下:

void reverse_part(char *str, int start, int end) //将字符串从start到end这一段逆序
{
	int i, j;
	char tmp;

	for (i = start, j = end; i < j; i++, j--)
	{
		tmp = str[i];
		str[i] = str[j];
		str[j] = tmp;
	}
}

void leftRound(char * src, int time)
{
	int len = strlen(src);
	int pos = time % len;
	reverse_part(src, 0, pos - 1); //逆序前段
	reverse_part(src, pos, len - 1); //逆序后段
	reverse_part(src, 0, len - 1); //整体逆序
}

字符串旋转结果

题目要求:

写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。

例如:给定s1 =AABCD和s2 = BCDAA,返回1

给定s1=abcd和s2=ACBD,返回0.

分析:

本题当然可以将所有旋转后的结果放到一个数组里,然后进行查找,但是这种做法既不好操作,也太费事,但是这题有一个很简单的做法:

其实ABCDE无论怎么旋,旋转后的所有结果,都包含在了ABCDEABCD这个字符串里了。

所以做法很简单,只需要将原字符串再来一遍接在后面,然后找一找待查找的字符串是不是两倍原字符串的子集即可。

int findRound(const char * src, char * find)
{
	char tmp[256] = { 0 }; //用一个辅助空间将原字符串做成两倍原字符串
	strcpy(tmp, src); //先拷贝一遍
	strcat(tmp, src); //再连接一遍
	return strstr(tmp, find) != NULL; //看看找不找得到
}

方法二:

只需要进行一一比较就好

#include<stdio.h>
#include<string.h>


void panduan(char* p1,char* p2,int len)
{
	int count = 0;
	int n = 0;
	for (n = 0; n < len; n++)
	{
		count = 0;
		int i = 0;
		for (i = 0; i <= n; i++)
		{
			if (*(p1 + i) == *(p2 + len - n - i-1))
			{
				
				count++;
			}
		}
		if (count == n + 1&& *(p1 + i+1) != *(p2 + len - n - i))
		{
			printf("%s左旋%d个字符得到%s", p1, count+1 , p2);
			break;
		}
	}
	if (count == 0)
	{
		printf("没有左旋");
	}
}


int main()
{
	char s1[10] = "abcd";
	char s2[10] = "dabc";
	gets(s1);
	gets(s2);
	int len = strlen(s1);
	panduan(s1, s2, len);
	return 0;
}

 

若有更多做题方法,题目讲解有误或还有不懂的地方,欢迎评论区留言或者私信!!!

 

 

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
C语言可以通过字符串处理函数来解析上位机发送的字符串命令,并根据命令行相应的处理。 首先,通过使用字符串处理函数如strlen和strcmp等函数,可以获取字符串命令的长度和比较字符串的内容。可以用strlen函数获取字符串的长度,然后逐个字符比较来判断命令的类型。例如可以使用strcmp函数来比较命令是否为指定的字符串。 其次,可以使用字符串处理函数如strtok函数来分割字符串命令,将字符串按照指定的分隔符分割成多个子串,而获取各个参数。可以使用strtok函数以分隔符为依据,将字符串命令分割成多个子串或标记,然后可以逐个处理这些子串。 然后,可以使用条件语句(如if-else语句)来根据命令类型行相应的处理。根据命令类型的不同,可以编写相应的功能函数或逻辑来实现对命令的处理。可以通过判断命令的关键字或使用哈希表等数据结构来确定应该执行哪一段代码。 最后,根据命令需要的参数类型和格式行参数解析和处理。对于需要带有参数的命令,可以使用字符串处理函数如atoi和atof等函数将字符串参数转换成相应的数据类型,以便行后续的操作。 综上所述,C语言可以通过字符串处理函数、条件语句和参数解析等方法来解析上位机字符串命令,并根据命令行相应的处理。这样可以实现上位机与下位机之间的命令交互和数据传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遇事问春风乄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值