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

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

1.jpeg


目录



   1、判断是不是字母

   2、斐波那契数列

   3、冒泡排序

   4、序列中删除指定数字

   5、打印水仙花数

   6、变种水仙花数

   7、有序序列判断


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;
}


2.png


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


3.png


2、斐波那契数列



   题目:编程实现求第n个斐波那契数

   例如:输入:5 输出:5

   输入:10, 输出:55

   输入:2, 输出:1


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


4.png


看到这个,我们有两种思路,其中一种就是递归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;
}


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



6.png

5.png6.png


大家可以看到,当我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项就会减少大量运算


7.png


3、冒泡排序



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


冒泡排序,首先我们要直到冒泡排序的核心思想:两两相邻元素进行比较。

那么具体是如何实现的呢?举个例子:

假如我们要对5 4 3 2 1,进行冒泡排序


8.png


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


#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;
}


大家来看结果:


9.png


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


4、序列中删除指定数字



   有一个整数序列(可能有重复的整数),现删除指定的某一个整数,输出删除指定数字之后的序列,序列中未被删除数字的前后位置没有发生改变。

   数据范围:序列长度和序列中的值都满足1≤n≤50

   输入描述:

   第一行输入一个整数(0≤N≤50)。

   第二行输入N个整数,输入用空格分隔的N个整数。

   第三行输入想要进行删除的一个整数。

   输出描述:

   输出为一行,删除指定数字之后的序列。


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


10.png


具体实现代码如下:


#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;
}


11.png


5、打印水仙花数



   求出0~100000之间的所有“水仙花数”并输出。

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


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


12.png

13.png


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

代码如下:

Plain Text

自动换行

plain

bash

Plain Text

Bash

Basic

C

C++

C#

CSS

Dart

Diff

Dockerfile

Erlang

Git

Go

GraphQL

Groovy

HTML

HTTP

Java

JavaScript

JSON

JSX

KaTeX

Kotlin

Less

Makefile

Markdown

MATLAB

Nginx

Objective-C

Pascal

Perl

PHP

PowerShell

Protobuf

Python

R

Ruby

Rust

Scala

Shell

SQL

PL/SQL

Swift

TypeScript

VB.net

Velocity

XML

YAML

sTeX

LaTeX

SystemVerilog

Tcl

Verilog

Vue

Lua

 

1

#include<stdio.h>

2

#include<math.h>

3

void print_daffodil()

4

{

5

  int i = 0;

6

  //用来计算i是n位数,n>=1

7

  for (i = 1; i <= 100000; i++)

8

  {

9

  int count = 1;

10

  int sum = 0;

11

  //将i的值赋值给tmp,计算是n位数

12

  int tmp = i;

13

  while (tmp/10)

14

  {

15

    count++;

16

    tmp /= 10;

17

  }

18

  //将i的值再次赋值给tmp,用来计算个、十、百、千......位的n次方之和

19

  tmp = i;

20

  while (tmp)

21

  {

22

    int set = tmp % 10;

23

    sum += (int)pow(set, count);

24

    tmp /= 10;

25

  }

26

  //进行判断

27

  if (sum == i)

28

  {

29

    printf("%d ", i);

30

  }

31

  }

32

}

33

int main()

34

{

35

  print_daffodil();

36

  return 0;

37

}


运行结果如下:


14.png


这里用到了库函数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时,表示有大有小,无序。否则有序


15.png


代码如下:


#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;
}


运行结果如下:


16.png


end


生活原本沉闷,但跑起来就会有风!诸君加油!!!

给个支持与鼓励吧,一起加油!❤


相关文章
|
7月前
|
存储 测试技术 C++
二叉树——经典练习题
二叉树——经典练习题
|
6月前
|
机器学习/深度学习 人工智能 C语言
|
6月前
|
C语言
|
7月前
|
存储 算法
数字三角形(很经典的动态规划问题)
数字三角形(很经典的动态规划问题)
|
程序员 C语言
初阶函数经典例题(2)
初阶函数经典例题(2)
|
7月前
|
算法
经典双指针算法试题(二)
经典双指针算法试题(二)
62 0
|
7月前
|
算法 容器
经典双指针算法试题(一)
经典双指针算法试题(一)
61 0
递归经典例题——汉诺塔
递归经典例题——汉诺塔
116 1
|
存储 算法
算法分类数组经典题目
算法分类数组经典题目
|
存储
【单链表经典习题讲解】(一)
【单链表经典习题讲解】(一)
68 0
【单链表经典习题讲解】(一)