C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法

这篇具有很好参考价值的文章主要介绍了C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

三步翻转法

三步翻转法是C语言中用来求旋转字符串的一种进阶方法,我们以具体例题对其进行介绍。

例:求一个字符串左旋n个字符后得到的新字符串

普通方法实现

我们知道,左旋一个字符一共分为三步:

  1. 将字符串的第一个字符存放到临时变量中;
  2. 将字符串中除’\0’外的所有字符整体向前挪动一位;
  3. 将tmp放在末尾’\0’的前面;

那么,我们左旋n个字符就只需要把这三步操作放在循环里面循环n次即可。

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

char* left_rotate(char arr[], int n)  //返回值为char*,用于实现链式访问
{
	assert(arr != NULL);
	char* ret = arr;  //记录arr的地址用于返回
	int len = strlen(arr);
	n %= len;  //使得当n大于字符串长度时我们仍只需要左旋小于len次,提高效率,也避免越界
	int i = 0;
	int j = 0;
	for (i = 0; i < n; i++)
	{
		char tmp = arr[0];   //将字符串中的第一个位置的字符拿出来
		for (j = 0; j < len - 1; j++)   //将字符串整体向前挪动一个字符('\0'不动)
		{
			arr[j] = arr[j + 1];
		}
		arr[len - 1] = tmp;  //将第一个字符放到末尾'\0'的前面
	}
	return ret;
}

int main()
{
	char arr[] = "abcdef";
	int n = 0;
	scanf("%d", &n);
	left_rotate(arr, n);  //将arr左旋n个字符
	printf("%s\n", arr);
	return 0;
}

C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法

三步翻转法实现

三步翻转法的原理如下:假设我们要左旋字符串 “abcdef” 中的 “ab” ,那么我们只需要进行三步操作即可:

  1. 翻转 “ab” ;
  2. 翻转 “cdef” ;
  3. 翻转这个字符串 “abcdef” ;

即 ab cdef -> ba cdef -> ba fedc -> cdef ab,用三次逆序操作实现旋转字符串,所以此方法被称作三步翻转法。

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

void reverse(char* left, char* right)  //逆序字符串
{
	assert(left && right);
	while (left <= right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

char* left_rotate(char arr[], int n)   //返回值为char*,用于实现链式访问
{
	assert(arr != NULL);
	char* ret = arr;  //记录arr的地址用于返回
	int len = strlen(arr);
	n %= len;   //使得当n大于字符串长度时我们仍只需要左旋小于len次,提高效率,也避免越界
	reverse(arr, arr + n - 1);        //翻转前面n个字符
	reverse(arr + n, arr + len - 1);  //翻转后面n个字符
	reverse(arr, arr + len - 1);      //翻转整个字符串
	return ret;
}

int main()
{
	char arr[] = "abcdef";
	int n = 0;
	scanf("%d", &n);
	left_rotate(arr, n);  //将arr左旋n个字符
	printf("%s\n", arr);
	return 0;
}

C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法


杨氏矩阵

杨氏矩阵的介绍

杨氏矩阵。是对组合表示理论和舒伯特演算很有用的工具。它提供了一种方便的方式来描述对称和一般线性群的群表示,并研究它们的性质。杨氏矩阵是剑桥大学大学数学家阿尔弗雷德·扬在1900年提出。然后在1903年,它被用于格奥尔格·弗罗贝纽斯的对称群研究中。它的理论得益于许多数学家的贡献得到进一步发展,包括珀西·麦克马洪,W.V.D.霍奇,G.deB.罗宾逊,吉安·卡咯罗塔,阿兰拉斯克斯,马塞尔·保罗斯库森博格和理查德·P·史丹利。(来源:百度百科)

从图像上来看,杨氏矩阵就是下面这样的矩阵:C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法

其实,杨氏矩阵就是一个二维数组,只不过这个二维数组的每行是递增的、每列也是递增的。

例:有一个二维数组,数组的每行从左到右是递增的,每列从上到下是递增的。在这样的数组中查找一个数字是否存在。

要求: 时间复杂度小于O(N)。

我们就以上面这个二维数组为例,由于题目要求时间复杂度小于O(N),所以我们不能通过循环便利数组元素的方式求解。

由于杨氏矩阵行从左到右是递增的,每列从上到下是递增的,所以我们可以拿矩阵中左下角或者右上角的元素与目标元素进行比较,以右上角的元素3为例,我们知道,3是这一行中最大元素,同时是这一列中最小的元素,那么如果目标元素小于3,那么我们就可以排除掉3所在这一整列,而如果目标元素大于3,我们则可以排除3所在的这一整行,这样提高效率,达到题目时间复杂度的要求。C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法

代码实现

#include <stdio.h>

int find_num(int arr[3][3], int row, int col, int n)
{
	int x = 0;
	int y = col - 1;  //找到右上角的元素
	int i = 0;
	int j = 0;
	for (i = x; i < row; i++) //x<row :查找的边界
	{
		for (j = y; j >= 0; j--)  //y>=0 :查找的边界
		{
			if (n > arr[x][y])
				x++;  //如果目标元素大于右上角元素,则x++,直接查找第二行的元素
			else if (n < arr[x][y])
				y--;  //如果目标元素小于右上角元素,则y--,直接查找前面一列的元素
			else
				return 1;  //找到返回1
		}
	}
	return 0;  //没找到返回0
}

int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int n = 0;  //要查找的数字
	scanf("%d", &n);
	int ret = find_num(arr, 3, 3, n);
	if (ret == 1)
		printf("找到了\n");
	else
		printf("没找到\n");
	return 0;
}

C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法

代码完善

我们发现上面的代码虽然能够实现题目的要求,但是它的功能是不完善的,如果找到了目标元素,我们最好是能够返回目标元素所在的下标;由于二维数组的下标有两个数,所以不能通过返回值的方式直接带回,而是可以通过一些其他方式:

  1. 通过结构体带回;
  2. 通过指针数组带回;
  3. 通过传递两个变量的地址改变变量的值来标记;
  4. 通过两个全局变量实现;

虽然使用全局变量的方式十分简单,但是由于全局变量十分不安全,所以不推荐使用,这里我提供结构体带回的实现方式。

#include <stdio.h>

struct flag
{
	int x;
	int y;
}f;

int find_num(int arr[3][3], int row, int col, int n)
{
	int x = 0;
	int y = col - 1;  //找到右上角的元素

	//结构体变量的初始化,注意这里不要初始化为0 0,应该初始化为两个无意义的数,因为目标元素可能在0 0 处
	f.x = -1;
	f.y = -1;

	int i = 0;
	int j = 0;
	for (i = x; i < row; i++) //x<row :查找的边界
	{
		for (j = y; j >= 0; j--)  //y>=0 :查找的边界
		{
			if (n > arr[x][y])
				x++;  //如果目标元素大于右上角元素,则x++,直接查找第二行的元素
			else if (n < arr[x][y])
				y--;  //如果目标元素小于右上角元素,则y--,直接查找前面一列的元素
			else
			{
				f.x = x;  //找到了就使用结构体记录坐标
				f.y = y;
				return 1;  //找到返回1
			}
		}
	}
	return 0;  //没找到返回0
}

int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int n = 0;  //要查找的数字
	scanf("%d", &n);
	int ret = find_num(arr, 3, 3, n);
	if (ret == 1)
		printf("arr[%d][%d] = %d\n", f.x, f.y, n);
	else
		printf("没找到\n");
	return 0;
}

C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法


辗转相除法

欧几里得算法又称辗转相除法,是指用于计算两个非负整数a,b的最大公约数。应用领域有数学和计算机两个方面。计算公式是:

gcd(a,b) = gcd(b,a mod b);

注:最小公倍数的计算公式如下:

lcm(a,b) = a*b/gcd(a,b);

假如需要求 1997 和 615 两个正整数的最大公约数,用欧几里得算法,是这样进行的:

1997 / 615 = 3 (余 152)

615 / 152 = 4(余7)

152 / 7 = 21(余5)

7 / 5 = 1 (余2)

5 / 2 = 2 (余1)

2 / 1 = 2 (余0)

至此,最大公约数为1

以除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数,所以就得出了 1997 和 615 的最大公约数 1。

代码实现(循环版本)

#include <stdio.h>

int gcd(int m, int n)
{
	int rem = 0;
	while (n > 0)
	{
		rem = m % n;
		m = n;
		n = rem;
	}
	return m;
}

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int ret = gcd(a, b);
	printf("%d\n", ret);
	return 0;
}

C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法

代码实现(递归版本)

#include <stdio.h>

int gcd(int m, int n)
{
	if (n == 0)
		return m;
	return gcd(n, m % n);
}

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int ret = gcd(a, b);
	printf("%d\n", ret);
	return 0;
}

C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法

练习题:小乐乐与欧几里得_牛客题霸_牛客网 (nowcoder.com)文章来源地址https://www.toymoban.com/news/detail-431092.html

#include <stdio.h>
int main()
{
	long long n = 0;
	long long m = 0;
	while (scanf("%lld %lld", &n, &m) == 2)
	{
		long long a = n;  //将n和m赋值给a和b,防止使用辗转相除法改变它们的值
		long long b = m;
		long long gcd = 0;
		long long lcm = 0;
		while (b)  //辗转相除法求最大公约数
		{
			long long rem = a % b;
			a = b;
			b = rem;
		}
		gcd = a;
		lcm = n * m / gcd;  //最小公倍数 = n * m /最大公约数
		printf("%lld\n", gcd + lcm);
	}
	return 0;
}

到了这里,关于C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】每日一题(杨氏矩阵查找数)

    既然在杨氏矩阵中查找数,那什么是杨氏矩阵呢? 矩阵的每行从 左到右是递增 的,矩阵从 上到下是递增 的。 例如: 看到这题我们马上就可以想到 遍历一遍数组 ,但无疑这是效率最低的算法,就不展开详细来讲了 那还有什么样的算法呢? 我们发现这歌矩阵是特殊的: 左

    2024年02月09日
    浏览(29)
  • C语言:杨氏矩阵中查找某数(时间复杂度小于O(N))

    有一个 数字矩阵 ( 二维数组 ), 矩阵的 每行从左到右是递增的 , 矩阵从上到下是递增的 , 请编写程序在这样的矩阵中查找某个数字是否存在, 要求: 时间复杂度小于O(N) 。                       =========================================================================            

    2024年02月15日
    浏览(33)
  • 【C语言】经典题目(二)

    C站的小伙伴们,大家好呀^^! 这一篇文章是C语言之经典题目,快来跟我一起进入C语言的世界吧!💞 C语言其他刷题篇在这里哦: 【C】语言经典题目(一) 【C语言】字符串—刷题篇 给出三角形的边长,求三角形的面积。 利用海伦公式求三角形面积 area=根号下 s*(s-a)*(s-b

    2024年02月07日
    浏览(31)
  • C语言经典面试题目(十八)

    1、如何在C语言中实现堆排序算法? 堆排序是一种利用堆数据结构进行排序的算法。它的基本思想是首先将待排序的数组构建成一个最大堆(或最小堆),然后逐步将堆顶元素与堆中最后一个元素交换,并重新调整堆,使得剩余元素继续满足堆的性质,最终得到有序序列。

    2024年03月18日
    浏览(38)
  • C语言天花板——指针(经典题目)

    指针我们已经学习的差不多了,今天我来给大家分享几个经典的题目,来让我们相互学习🏎️🏎️🏎️     ​       ​  图解: ​   ​     ​   ​       ​   ​    相信大家一定从今天的题目当中收获满满,希望大家有美好的一天!💓💓💓

    2024年01月17日
    浏览(39)
  • 经典C语言题目程序题(函数篇)

    经典的C语言函数篇题目,看完你期末考试就没有问题了!快来一起看看吧!!! 目录 1.编写一个函数,可以算出 任意两个整数的和,并返回相应的结果 2. 编写一个函数可以求出任意三个整数之中的最大值,并返回其最大值 3.编写一个函数,可以实现给出算数运算的功能,

    2024年02月01日
    浏览(42)
  • C语言中链表经典面试题目

    🐶博主主页: @ᰔᩚ. 一怀明月ꦿ  ❤️‍🔥 专栏系列: 线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++ 🔥 座右铭: “不要等到什么都没有了,才下定决心去做” 🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀   目录 环

    2024年02月02日
    浏览(65)
  • 找凶手,定名次,字符串旋转,杨氏矩阵

    1.找凶手问题: //题目名称: //猜凶手 //题目内容: //日本某地发生了一件谋杀案,警察通过排查确定凶手必为4个嫌疑犯的一个。 //以下为4个嫌疑犯的供词: //A说:不是我 //B说:是C //C说:是D //D说:C在胡说 //已知3个人说的是真话,1个人说的是假话。 //请根据这些信息,写

    2023年04月23日
    浏览(24)
  • 【C语言】辗转相除法求最大公约数(详解)

    辗转相除法(又称欧几里德算法)是一种用于求解两个整数的最大公约数的方法。本文将使用C语言来实现辗转相除法,并对其原理进行解释。 辗转相除法的原理非常简单。假设有两个整数a和b,其中a b。通过对a除以b求余数,得到余数r1。然后把b除以r1求余数,得到余数r2。如

    2024年02月07日
    浏览(46)
  • C语言辗转相除法运用 24/1/22笔记错题整理

    题目: 思路:一开始用最普通的方法去解题,计算量较大,但是 求最大公约数常用的有两种简单方法,一是九章算术中的 更相减损术 :大数减小数直到相等,相等的数即最大公约数,该算法 时间复杂度约为O(N) ;二是欧几里得的 辗转相除法 :大数除以小数取余数(相当于模

    2024年01月23日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包