zl程序教程

您现在的位置是:首页 >  其他

当前栏目

经典例题(二)——超经典例题的归纳总结

2023-03-07 09:43:22 时间

目录

1、判断是不是字母

题目:判断输入的字符是不是字母。 输入描述: 多组输入,每一行输入一个字符。 输出描述 针对每组输入,输出单独占一行,判断输入字符是否为字母,如果是,输出 _is an alphabet.如果不是,输出:_is not an alphabet.

这道题看到后其实很好入手,字母也就是A-Z,a-z,直接入手即可,看如下代码:

#include <stdio.h>
int main()
{
    char letter = 0;
    while ((scanf("%c",&letter) != EOF))
    {
        if ((letter >= 'A' && letter <= 'Z') || (letter >= 'a' && letter <= 'z'))
        {
            printf("%c is an alphabet.\n", letter);
        }
        else
        {
            printf("%c is not an alphabet.\n", letter);
        }
        //gerchar清理掉\n
        getchar();

    }

    return 0;
}

这里有一点需要注意,就是题目要求是每行输入一个字符,而我们使用scanf,其实当我们输入一个字符的时候,scanf还读取到了\n,即换行,就是我们每次输入一个字符后,还按下了Enter,也就是换行,所以其实我们输入的内容是一个字符+一个\n,所以我们在循环的内容里加上了getchar(),用来吸收\n,每次对一个字符进行判断完后,getchar()都会吸收剩下的\n。

2、斐波那契数列

题目:编程实现求第n个斐波那契数 例如:输入:5 输出:5 输入:10, 输出:55 输入:2, 输出:1

做这个题首先要知道什么是斐波那契数列,如下图:

看到这个,我们有两种思路,其中一种就是递归Fib(n)=Fib(n-2)+Fib(n-1)。 方法一:递归

#include<stdio.h>
int Fib(int n)
{
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);

}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fib(n);
	 
	printf("%d", ret);

	return 0;
}

这种方法虽然很容易想到,但是存在一个弊端,就是运算量太大了,看如下图:

大家可以看到,当我i们求第55项时,程序已经陷入死循环,卡在这里了。这便是它的缺陷,大家看另一种方法。 方法二、非递归 假如要求第五项,我们直接从前面加到第五项,即我们从第一项开始正着推 第一项:1 第二项:1 第三项:1+1=2 第四项:2+1=3 第五项:3+2=5

运算量大大减少,具体用代码如何实现呢?如下:

#include<stdio.h>

int Fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;
	//前两项都是1
	while (n > 2)
	{
		//Fib(3)=Fib(1)+Fib(2)
		c = a + b;
		//此时把Fib(2)赋值给a,把Fib(3)赋值给b,再次循环求Fib(4)......
		a = b;
		b = c;
		n--;
	}
	return c;
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fib(n);

	printf("%d", ret);

	return 0;
}

而这时,我们求第55项就会减少大量运算

3、冒泡排序

题目:实现一个对整形数组的冒泡排序(升)

冒泡排序,首先我们要直到冒泡排序的核心思想:两两相邻元素进行比较。 那么具体是如何实现的呢?举个例子: 假如我们要对5 4 3 2 1,进行冒泡排序

了解这个后我们开始入手写代码:

#include<stdio.h>

int main()
{
	int arr[] = { 2,7,6,6,6,0,8,2,8,2 };
	//元素个数
	int sz = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int t = 0;
	//趟数=元素个数-1
	for (t = 0; t < sz - 1; t++)
	{
		//排序次数
		int j = 0;
		for (j = 0; j < sz - 1 - t; j++)
		{
			//两两排序
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
	//打印排序后的
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

大家来看结果:

核心思想:相邻元素两两排序

4、序列中删除指定数字

有一个整数序列(可能有重复的整数),现删除指定的某一个整数,输出删除指定数字之后的序列,序列中未被删除数字的前后位置没有发生改变。 数据范围:序列长度和序列中的值都满足1≤n≤50 输入描述: 第一行输入一个整数(0≤N≤50)。 第二行输入N个整数,输入用空格分隔的N个整数。 第三行输入想要进行删除的一个整数。 输出描述: 输出为一行,删除指定数字之后的序列。

这里我们注意到,序列长度和序列中的值都满足1≤n≤50,那我们可以将删除的数赋值为0,然后打印时遇到0直接跳过,就好象这样:

具体实现代码如下:

#include<stdio.h>
int main()
{
    int n = 0;
    scanf("%d", &n);
    int arr[50];
    int i = 0;
    for (i = 0; i < n; i++)
    {
        scanf("%d ", &arr[i]);
    }
    //要删除的整数
    int del = 0; 
    scanf("%d", &del);
    for (i = 0; i < n; i++)
    {
        if (arr[i] == del) 
            //赋值
            arr[i] = 0;
    }
    for (i = 0; i < n; i++) //打印
    {
        //arr[i]==0的时候,表达式为假,不执行打印
        if (arr[i])
        {
            printf("%d ", arr[i]);
        }
    }
    return 0;
}

5、打印水仙花数

求出0~100000之间的所有“水仙花数”并输出。 “水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如:153=1^3 + 53+33,则153是一个“水仙花数”。

其实真正的水仙花数是三位数,这里我们根据题目的要求来做题就行。

首先,我们要确定这是一个几位数,然后把这个数拆分开来,再来求n次方之和,与这个数相比较,如果相等,就满足题目中的水仙花数要求。 代码如下:

#include<stdio.h>
#include<math.h>

void print_daffodil()
{
	int i = 0;
	//用来计算i是n位数,n>=1
	for (i = 1; i <= 100000; i++)
	{
		int count = 1;
		int sum = 0;
		//将i的值赋值给tmp,计算是n位数
		int tmp = i;
		while (tmp/10)
		{
			count++;
			tmp /= 10;
		}
		//将i的值再次赋值给tmp,用来计算个、十、百、千......位的n次方之和
		tmp = i;
		while (tmp)
		{
			int set = tmp % 10;
			sum += (int)pow(set, count);
			tmp /= 10;
		}
		//进行判断
		if (sum == i)
		{
			printf("%d ", i);
		}
	}
}

int main()
{
	print_daffodil();
	return 0;
}

运行结果如下:

这里用到了库函数pow(a,b),求a的b次方,包含头文件<math.h>,返回值为double,这里我们用(int),强制类型转换为int。(因为我们所求的都是整数,所以结果不会有偏差)

6、变种水仙花数

变种水仙花数 - Lily Number:把任意的数字,从中间拆分成两个数字,比如1461 可以拆分成(1和461),(14和61),(146和1),如果所有拆分后的乘积之和等于自身,则是一个Lily Number。 例如: 655 = 6 * 55 + 65 * 5 1461 = 1461 + 1461 + 146*1 求出 5位数中的所有 Lily Number。 输入描述: 无 输出描述: 一行,5位数中的所有 Lily Number,每两个数之间间隔一个空格。

上一题的变形版本,首先还是需要求的这个数是几位数,然后再计算并判断,理解了上一题,这题就很简单了

代码如下:

#include<stdio.h>
#include<math.h>

int main()
{
	int i = 0;
	for (i = 10000; i <= 100000; i++)
	{
		int sum = 0;
		//(%10)^(位数-1)* (/10)^(位数-1),进行求和
		int count = 0;
		int tmp = i;
		while (tmp /= 10)
		{
			count++;
		}
		tmp = i;
		while (count)
		{
			int set = pow(10, count);
			int m = (tmp % set)* (tmp / set);
			sum += m;
			count--;
		}

		if (sum == i)
		{
			printf("%d ", i);
		}
	}

	return 0;
}

7、有序序列判断

输入一个整数序列,判断是否是有序序列,有序,指序列中的整数从小到大排序或者从大到小排序(相同元素也视为有序)。 数据范围: 3≤n≤50 序列中的值都满足1≤val≤100 输入描述: 第一行输入一个整数N(3≤N≤50)。 第二行输入N个整数,用空格分隔N个整数。 输出描述: 输出为一行,如果序列有序输出sorted,否则输出unsorted。

思路:将序列的后一个数与前一个相比,无序即有大有小,否则就有序,而有大或者有小时各给flag1,flag2赋值1 只有两者同时为1时,表示有大有小,无序。否则有序

代码如下:

#include <stdio.h>
int main()
{
    int arr[55] = { 0 };
    int n = 0;
    int flag1 = 0;
    int flag2 = 0;
    int i = 0;
    scanf("%d", &n);
    for (i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
        if (i > 0)
        {
            if (arr[i] < arr[i - 1])
            {
                flag1 = 1;
            }
            else if (arr[i] > arr[i - 1])
            {
                flag2 = 1;
            }
        }
    }
    if (flag1 && flag2)
        printf("unsorted\n");//只有当flag1和flag2都为1的时候序列无序
    else
        printf("sorted\n");
    return 0;
}

运行结果如下:

end

生活原本沉闷,但跑起来就会有风!诸君加油!!! 给个支持与鼓励吧,一起加油!❤