C语言求N!(N的阶乘) 求1-10每个数阶乘之和 在一个有序数组中查找具体的某个数字N

最近又开始重新过了一边C语言,到了分支和循环语句的部分,做了几个练习题来分享一下,话不多说,进入正题!

第一道题目:求N!的值

这里呢,因为是要求N的阶乘,计算公式为1*2*3*...*n;    我们应该敏感的是,这里出现了1,2,3,这样的连续数字,我们最先想到的肯定是循环语句;

用for循环来做:

//求N的阶乘
int main()
{
	int a = 0;
	int i = 0;
	int sum = 1;
	scanf("%d",&a);        //输入我们要求的n
	for (i = 1; i <= a; i++)
	{
		sum = sum * i;
	}
	printf("%d\n",sum);
	return 0;
}

这里选择1为i的初始值,是因为,我们的计算是从1,开始的,而判断条件为i<=a;是因为,我们算到最后是要乘以a的;所以说以i<=a;为判断条件;

用while循环来做:

int main()
{
	int a = 0;
	int i = 1;
	int sum = 1;
	scanf("%d",&a);
	while (i <= a)
	{
		sum = sum * i;
		i++;
	}
	printf("%d\n",sum);
	return 0;
}

第二道题目:求1-10每个数的阶乘之和

这道题目我们可以联系上一道题目来做,因为上一道题目,求的是n的阶乘,把n依次换成1,2,3,4等数字,再把每个数的阶乘加起来就算出来了;这个时候我们就用到了,嵌套的循环语句;

常规思想:

//求1-10各个数阶乘的和
int main()
{
	int i = 0;
	int a = 0;
	int sum = 1;
	int sum1 = 0;
	for (i = 1; i <= 10; i++)
	{
		for (a = 1; a <= i; a++)
		{
			sum = sum * a;
		}
		sum1 = sum + sum1;
		sum = 1;
	}
	printf("%d\n",sum1);
}

可以看到,我们内部的for循环,是和上到题目的for循环是一样的,所以说,我们内部的for循环是计算每个数的阶乘,而外部的for循环的作用,就是将1,2,3,4,。。。,10,这是个数分别输入进去的;最后,再把每次的计算结果相加就得到我们需要的结果啦;

仔细探索:

我们可以仔细对比一下,我们计算

1的阶乘为1

2的阶乘为1*2

3的阶乘为1*2*3

其实,不难发现,每次计算的结果都是在之前的一次的结果之上在乘以i;我们就可以做个更简单的过程出来;

//求1-10各个数阶乘的和
int main()
{
	int i = 0;
	int a = 0;
	int sum = 1;
	int sum1 = 0;
	for (i = 1; i <= 10; i++)
	{
		sum = sum * i;
		sum1 += sum;
	}
	printf("%d\n",sum1);
}

第三道题目:在一个有序数组中查找具体的某个数字N

常规思路:

我最先想到的就是可以把整个数组遍历一遍,逐个对比在输出结果

//求有序数组的中的某个数n
int main()
{
	int i = 0;
	int a = 0;
	int arr[] = { 1,2,3,4,5,6,7,8,9,10,0 };
	int len = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < len; i++)
	{
		if (arr[i] == 8)
		{
			a = arr[i];
			break;
		}
	}
	printf("%d\n",a);
}

思路是先根据sizeof();函数计算出数组的长度,在使用for循环以数组长度为判断条件,将数组元素逐个对比,并输出结果;

反思,这样的确可以输出正确的结果,但是,我们写程序要考虑,程序的时间复杂度,我们这样遍历一遍,数组元素少的话还不明显,如果,数组的元素很多呢,程序就会变得很慢;

新学的思路:

在学习的过程,老师提供了一个二分查找也叫拆分查找

代码如下:

int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	int k = 8;
	int len = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int right = len-1;
	len = (left + right)/ 2;

	while (left <= right)
	{
		if (arr[len] < k)
		{
			left = len+1;
			len = (left + right) / 2;
		}
		else if (arr[len] > k)
		{
			right = len - 1;
			len = (right + left) / 2;

		}
		else
		{
			printf("找到了值为%d,下标为:%d\n", arr[len],len);
			break;
		}	
	}
	if (left > right)
	{
		printf("实在找不到,求放过!!");
	}
	return 0;
}

这里的思路为,我们抓住一个关键点,这个数组是一个有序数组,所以我们可以进行二分查找,根据求出的数组长度,确定数组的中间数字,并与我们要查的数字k进行比较;        

        如果,比k小,那么我们要找的数字k还在中间数字的右边,所以,以中间数字的下标+1,作为我们查找范围的第一个下标,查找范围的最后一个数字还为数组最后一个;

        如果,比k大,那么我们要找的数字k还在中间数字的左边,所以,以中间数字的下标-1,作为我们查找范围的最后个-下标,查找范围的第一个数字还为数组的一个元素;

一次步骤循环就行,在判断条件的外面再加上一个while循环,判断条件为left<=right;的时候循环结束;

如果,我么定义的left为查找范围的第一个数字,right为查找范围的最后一个数字,最后循环到left>right的时候,说明已经不是我们想要的范围了;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值