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

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

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


望诸君努力,共同进步!


相关文章
|
6月前
|
存储 测试技术 C++
二叉树——经典练习题
二叉树——经典练习题
|
2月前
|
机器学习/深度学习 存储 算法
经典算法代码
这段代码展示了多个经典算法,包括:穷举法解决“百钱买百鸡”问题;递推法计算“猴子吃桃”问题;迭代法求解斐波那契数列及折纸高度超越珠峰的问题。同时,还提供了希尔排序算法实现及披萨票务订购系统和汉诺塔问题的链表存储解决方案。每部分通过具体案例解释了算法的应用场景与实现方法。
31 3
|
5月前
|
机器学习/深度学习 人工智能 C语言
|
5月前
|
C语言
|
程序员 C语言
初阶函数经典例题(2)
初阶函数经典例题(2)
|
6月前
|
算法
经典双指针算法试题(二)
经典双指针算法试题(二)
56 0
|
6月前
|
算法 容器
经典双指针算法试题(一)
经典双指针算法试题(一)
59 0
|
存储 算法
算法分类数组经典题目
算法分类数组经典题目
|
算法
贪心算法的思路和典型例题
贪心算法的思路和典型例题
|
SQL Rust Dart
经典例题(二)——超经典例题的归纳总结
经典例题(二)——超经典例题的归纳总结
143 0
经典例题(二)——超经典例题的归纳总结
下一篇
无影云桌面