经典例题(一)——经典例题的归纳总结。

简介: 经典例题(一)——经典例题的归纳总结。

1.jpeg


题目



   1、素数打印

   2、二分查找

   3、数组交换

   4、月份打印

   5、字母大小写转换

   6、字符串逆序并打印


1、素数打印



   题目:实现一个函数,判断一个数是不是素数。利用上面实现的函数打印100到200之间的素数。


这里,我们要先了解素数的定义,素数也叫质数 ,即在正整数中,除了1与本身之外没有其他约数的数(1除外)。

方法一:

也就是说,这个数只能被1和它本身整除。了解这一点后我们开始入手写代码,在这里我们最容易想到的方法就是试除法,即从2开始,不断地对那个数进行试除,假设这个数是n,直到试除到n(不包含n)为止,如果没有出现可以被整除的数,则n就是素数。


这里我们先来看一下如何实现对一个数是否为素数的判定:


#include<stdio.h>
void is_prime(int i)
{
  //用[2,i)之间的数进行试除
  int j = 0;
  //这里我们定义一个变量,假如这个变量最后是1,说明它是素数
  //                     假如是0,说明不是素数。
  int flag = 1;
  for (j = 2; j < i; j++)
  {
  //==0,说明这个数能被j整除
  if (i % j == 0)
  {
    //能被整除,说明i不是素数,给flag赋值为0
    flag = 0;
    printf("%d 不是素数", i);
    break;//没有继续试除的必要了,因为已经出现别的约数了,可以直接停止循环
  }
  }
  //经历以上循环后,如果flag还是1,说明没有别的约数了。即,i是素数
  if (flag == 1)
  {
  printf("%d 是素数", i);
  }
}
int main()
{
  //如果一个正整数除了1和自己之外,再没有其他的约数,则该数据为素数,具体方式如下
  int i = 0;
  scanf("%d", &i);
  //注意一点,1不是素数
  if (i == 1)
  {
  printf("%d 不是素数", i);
  }
  else
  {
  //进行素数判定
  is_prime(i);
  }
  return 0;
}


2.png


这里我们需要注意的是,=与==的区别,前者为赋值,后者是用来判断相等,千万不要用混了。


但是,上述方法有一个缺陷:就是超过i一半的数据,肯定不是i的倍数,上述进行了许多没有意义的运算,因此可以换一种方法,大家看举个例子,假如我们要判断100是不是素数,我们有必要从2试除到99吗?答案是否定的,我们只需要试除到它的开平方,也就是10,就可以判定是否为素数。以此类推来判断别的数


这里就需要用到库函数,sqrt(),专门用来求开平方的,使用必须包含头文件<math.h>


方法二:优化后:


#include<stdio.h>
#include<math.h>
void is_prime(int i)
{
  //用[2,sqrt(i)]之间的数进行试除,避免大量重复运算
  int j = 0;
  int flag = 1;
  for (j = 2; j <=sqrt(i); j++)
  {
  if (i % j == 0)
  {
    flag = 0;
    printf("%d 不是素数", i);
  }
  }
  if (flag == 1)
  {
  printf("%d 是素数", i);
  }
}
int main()
{
  int i = 0;
  scanf("%d", &i);
  //注意一点,1不是素数
  if (i == 1)
  {
  printf("%d 不是素数", i);
  }
  else
  {
  //进行素数判定
  is_prime(i);
  }
  return 0;
}


这么做就避免了大量重复计算。

接下来,了解这个后,进行打印1-100之间的素数就容易多了

题解:


#include<stdio.h>
#include<math.h>
//打印1-100之间的素数
void print_prime()
{
  int j = 0;
  int v = 0;
  for (v = 100; v <= 200; v++)
  {
  int prime = 1;//假设1为素数,0不是素数
  for (j = 2; j <= sqrt(v); j++)
  {
    if (v % j == 0)
    {
    prime = 0;
    break;
    }
  }
  if (prime == 1)
  {
    printf("%d ", v);
  }
  }
}
void is_prime(int i)
{
  //用[2,sqrt(i)]之间的数进行试除,避免大量重复运算
  int j = 0;
  int flag = 1;
  for (j = 2; j <=sqrt(i); j++)
  {
  if (i % j == 0)
  {
    flag = 0;
    printf("%d 不是素数\n", i);
  }
  }
  if (flag == 1)
  {
  printf("%d 是素数\n", i);
  }
}
int main()
{
  int i = 0;
  scanf("%d", &i);
  //注意一点,1不是素数
  if (i == 1)
  {
  printf("%d 不是素数\n", i);
  }
  else
  {
  //进行素数判定
  is_prime(i);
  //打印素数
  print_prime();
  }
  return 0;
}


2、二分查找



   编写代码在一个整形有序数组中查找具体的某个数

   要求:找到了就打印数字所在的下标,找不到则输出:找不到。


我们先了解以下什么是二分查找:如图所示


3.png

了解后我们开始入手答题:


#include<stdio.h>
int main()
{
  //定义查找的数
  int k = 0;
  //定义整型数组
  int arr[] = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25 };
  int left = 0;//左下标
  //右下标为总元素个数-1,因为下标从0开始
  int right = sizeof(arr) / sizeof(arr[0]) - 1;
  printf("请输入要查找的数:->");
  scanf("%d", &k);
  //左下标始终小于右下标,当相等时就说明找到那个数了
  while (left <= right)
  {
  //中间坐标
  int mid = (right + left) / 2;
  //中间坐标对应元素<要求的,那么新的查找区域左边坐标就变成了mid+1,右边不变
  if (arr[mid] < k)
  {
    left = mid + 1;
  }
  //中间坐标对应元素>要求的,那么新的查找区域右边坐标就变成了mid-1,左边不变
  if (arr[mid] > k)
  {
    right = mid - 1;
  }
  //左右坐标相等,说明确定这个值了
  if (arr[mid] == k)
  {
    printf("找到了,下标为%d", mid);
    break;//找到结果,中止循环
  }
  }
  //左下标大于右下标说名这个数是不存在的
  if (left > right)
  {
  printf("找不到");
  }
  return 0;
}


4.png


注意一点,一定要是有序的数组!!!!从小到大或者从大到小


3、数组交换



   将数组A中的内容和数组B中的内容进行交换。(数组一样大)


方法1:


这里我们主要需要知道一点,就是如何完成两个数据的交换,举个例子,一瓶水,一瓶尿,如何让它们进行交换,肯定是需要借助第三个空瓶子,把水倒进空瓶子,再把尿倒进原来盛水的瓶子,在把空瓶子里的水倒进原来盛尿的瓶子,就完成了交换(话粗理不粗)


在C语言里也是一样


5.png


千万不可以直接a=b,b=a,如果一旦这样的话,直接第一步b就把a覆盖了。

理清后入手:


#include <stdio.h>
int main()
{
  int arr1[10] = { 0 };
  int arr2[10] = { 0 };
  int i = 0;
  printf("请输入10个数字:>");
  for (i = 0; i < 10; i++)
  {
  scanf("%d", &arr1[i]);
  }
  printf("请输入10个数字:>");
  for (i = 0; i < 10; i++)
  {
  scanf("%d", &arr2[i]);
  }
  //交换
  for (i = 0; i < 10; i++)
  {
  int tmp = arr1[i];
  arr1[i] = arr2[i];
  arr2[i] = tmp;
  }
  return 0;
}


这里就完成数组交换了:打印看一下


6.png


方法2:

当然,我们也可以用指针来解题,指针表示的是地址,我们把两个数组的地址都进行交换,也可以实现数组交换,如下:


#include<stdio.h>
//数组名表示首元素地址
void swap(int* arr, int* brr, int sz)
{
  int n = 0;
  for (n = 0; n < sz; n++)
  {
  //首元素地址也就是arr[0],brr[0]的地址,加1就表示arr[1]与brr[1]的地址
  //解引用后进行交换,也可以实现数组交换
  int tmp = *(arr + n);
  *(arr + n) = *(brr + n);
  *(brr + n) = tmp;
  }
}
int main()
{
  int arr[] = { 1,2,3,4,5,6,7,8 };
  int brr[] = { 9,10,11,12,13,14,15,16 };
  //数组一样大
  int sz = sizeof(arr) / sizeof(arr[0]);
  //进行交换
  swap(arr, brr, sz);
  int i = 0;
  //打印arr,brr
  printf("arr=");
  for (i = 0; i < sz; i++)
  {
  printf("%d ", arr[i]);
  }
  printf("\n");
  printf("brr=");
  for (i = 0; i < sz; i++)
  {
  printf("%d ", brr[i]);
  }
  return 0;
}

 

7.png


4、月份打印



   KiKi想获得某年某月有多少天,请帮他编程实现。输入年份和月份,计算这一年这个月有多少天。

   输入描述:

   多组输入,一行有两个整数,分别表示年份和月份,用空格分隔。

   输出描述:

   针对每组输入,输出为一行,一个整数,表示这一年这个月有多少天。


方法一:

这里我们要知道,闰年2月有29天,平年28天,所以我们要进行闰年的判断,这里我们有两种方法,

第一种就是直接列举,把每个月份都列举出来,平年与闰年只有2月不同,如下;


#include <stdio.h>
int main()
{
    int year = 0;
    int month = 0;
    //多组输入
    while (scanf("%d %d", &year, &month) != EOF)
    {
        //判断是否闰年
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        {
            //2月
            if (month == 2)
            {
                printf("29\n");
            }
            //不是二月份的时候
            else
                goto end;
        }
        //不是闰年
        else
        {
            //2月
            if (month == 2)
            {
                printf("28\n");
            }
            //不是二月
            else
                goto end;
        }
        //列举
    end:
        if ((month == 4) || (month == 6) || (month == 9) || (month == 11))
        {
            printf("30\n");
        }
        else if ((month == 1) || (month == 3) || (month == 5) || (month == 7) || (month == 8) || (month == 10) || (month == 12))
        {
            printf("31\n");
        }
    }
    return 0;
}


这样做是可以,不过看起来可能有点繁琐,大家看另一个方法:

方法二:


#include<stdio.h>
int main()
{
  int y, m;
  //我们把一年的12个月的天数都放在数组里
  int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
//多组输入
  while (scanf("%d %d", &y, &m) != EOF)
  {
  //天数对应数组的下标,数组的下标就是月份-1,比如,一月对应的就是days[0]
  int day = days[m - 1];
  //判断闰年
  if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))
  {
    //如果是闰年,二月就+1天
    if (m == 2)
    {
    day += 1;
    }
  }
  printf("%d\n", day);
  }
  return 0;
}


8.png


是不是更简洁巧妙了一点,利用数组,列举所有月份天数,数组下标就是月份-1,如果是闰年,就二月对应(days[1]=28)+1即29天


5、字母大小写转换



   完成字母大小写转换,有一个字符,判断它是否为大写字母,如果是,将它转换成小写字母;反之则转换为大写字母。

   输入描述:

   多组输入,每一行输入一个字母。

   输出描述:

   针对每组输入,输出单独占一行,输出字母的对应形式


这题很简单,主要就是知道大写字母与小写字母的ASCLL码值相差32,下图为ASCLL表


9.png


题解:


#include<stdio.h>
int main()
{
    char letter = '0';
    //多组输入
    while (scanf("%c", &letter) != EOF)
    {
        if ((letter >= 'a') && (letter <= 'z'))
        {
            letter -= 32;
            printf("%c\n", letter);
        }
        else if ((letter >= 'A') && (letter <= 'Z'))
        {
            letter += 32;
            printf("%c\n", letter);
        }
    }
    return 0;


10.png


6、字符串逆序并打印



   将一个字符串str的内容颠倒过来,并输出。

   数据范围:1≤len(str)≤10000

   输入描述:

11.png  

输入一个字符串,可以有空格

   输出描述:

   输出逆序的字符串


这里首先就是注意,输入可以有空格,那我们就不能用scanf了,因为scanf只能读取到空格,改用gets。


这里我是利用指针求解的,当然也可以用递归(不容易理解),或者一些别的方法,在这里就先介绍本人的解题:


#include<stdio.h>
#include<string.h>
void reversed(char* str)
{
  //strlen专门求字符串长度,头文件<string.h>
  int len = strlen(str);
  //将str首元素地址放在left里
  char* left = str;
  //末元素地址=首元素地址+元素个数-1,存放在right里
  char* right = str + len - 1;
  //当left=right时,就说明没有可以调换的了
  while (left < right)
  {
  //地址解引用后就会找到所指向的元素,进行交换即可实现字符串逆序
  char tmp = *left;
  *left = *right;
  *right = tmp;
  left++;
  right--;
  }
  printf("%s", str);
}
int main()
{
  char str[10000] = { 0 };
  //输入字符串,在这里用gets是考虑到题目要求,输入可以存在空格,而scanf只能读取到空格,空格后面的读取不了
  gets(str);
  //数组名表示数组首元素地址
  reversed(str);
  return 0;
}


12.png


end


望诸君努力,共同进步!


相关文章
|
9月前
|
程序员 C语言
初阶函数经典例题(2)
初阶函数经典例题(2)
|
5月前
|
算法 容器
经典双指针算法试题(一)
经典双指针算法试题(一)
30 0
|
5月前
|
算法
经典双指针算法试题(二)
经典双指针算法试题(二)
34 0
|
7月前
|
存储 算法
算法分类数组经典题目
算法分类数组经典题目
|
8月前
|
算法
贪心算法的思路和典型例题
贪心算法的思路和典型例题
|
9月前
|
编译器
初阶函数递归经典例题(1)
初阶函数递归经典例题(1)
|
SQL Rust Dart
经典例题(二)——超经典例题的归纳总结
经典例题(二)——超经典例题的归纳总结
100 0
经典例题(二)——超经典例题的归纳总结
|
程序员 测试技术 C语言
【C语言经典例题】——程序员必须会的经典基础例题(三)
【C语言经典例题】——程序员必须会的经典基础例题(三)
|
算法
算法设计与分析/数据结构与算法实验3:矩阵连乘问题
算法设计与分析/数据结构与算法实验3:矩阵连乘问题
128 0
算法设计与分析/数据结构与算法实验3:矩阵连乘问题
|
算法
算法设计与分析/数据结构与算法实验4:添加括号数目问题
算法设计与分析/数据结构与算法实验4:添加括号数目问题
135 0
算法设计与分析/数据结构与算法实验4:添加括号数目问题