近期作业总结(函数,递归,二进制)

简介: 近期作业总结(函数,递归,二进制)

二分查找函数

写一个二分查找函数

功能:在一个升序数组中查找指定的数值,找到了就返回下标,找不到就返回-1。

int bin_search(int arr[], int left, int right, int key)
{
  int mid = 0;
  while (left <= right) {
    mid = (right + left) / 2;
    if (key<arr[mid]) {
      right = mid -1;
    }
    else if (key >arr[mid]) {
      left = mid +1;
    }
    else return -1;
  }
  
}

打印乘法口诀

void Mutitable(int N) {
  for (int i = 1; i <= N; i++) {
    for (int j = i; j <= i:j++) {
      printf("%d*%d=%d", i, j, i * j);
    }
    printf("\n");
  }
}

判断闰年

实现函数判断year是不是闰年

int is_leap_year(int year)
{
  if(((0 == year%4)&&(0!=year%100))||(0==year%400))
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

判断素数

#include <stdio.h>
#include<math.h>
int is_prime(int n)
{
  int i = 0;
  for (i = 2; i <= sqrt(n); i++)
  {
    if (0 == n % i)
    {
      return 0;//如果被其中一个数整除,那么结束程序
    }
  }
  return 1;
}
int main()
{
  int i = 0;
  for (i = 100; i <= 200; i++) {
    if (is_prime(i) == 1) {
      printf("%d ", i);
    }
  }
  return 0;
}

创建一个整形数组,完成对数组的操作

  1. 实现函数init() 初始化数组为全0
  2. 实现print()  打印数组的每个元素
  3. 实现reverse()  函数完成数组元素的逆置。
void init(int arr[], int sz)
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    arr[i] = 0;
  }
}
void reverse(int arr[], int sz) 
{
  int left = 0;
  int right = sz - 1;
  while (left < right) {
    int temp = arr[left];
    arr[left] = arr[right];
    arr[right] = temp;
    left++;
    right--;
  }
}
  1. 统计二进制中1的个数

这个题有两种方法,下面我将逐一介绍他们,并分析利弊。

方法一:思路:我们将该数据%2,如果除尽,则证明最后一位数字为0,如果未除尽,则最后一位为1。如果是1,则count++。

int Num(int n)
{
  int count = 0;
  while (n) 
  {
    if (n % 2 == 1) {
      count++;
      n = n / 2;//判断完毕后,将n右移一位
    }
  }
  return count;
}

该方法有一些缺陷:进行了大量的取模以及除法运算,取模和除法运算的效率本来就比较低。

方法二:

思路:一个int类型的数据,对应的二进制一共有32个比特位,可以采用位运算的方式一位一位的检测。

int Num(int n) {
  int count = 0;
  int i = 0;
  for (i = 0; i < 32; i++) {
    if ((n >> i) & 1 == 1) {
      count++;
    }
    return count;
  }
}

优点:用位操作代替取模和除法运算,效率稍微比较高

 缺陷:不论是什么数据,循环都要执行32次

方法三:

用相邻的两个数据进行按位与运算。

我们观察9999:‭10 0111 0000 1111‬按位与下一位的情况:

第一次循环:n=9999   n=n&(n-1)=9999&9998= 9998

第二次循环:n=9998   n=n&(n-1)=9998&9997= 9996

第三次循环:n=9996   n=n&(n-1)=9996&9995= 9992

第四次循环:n=9992   n=n&(n-1)=9992&9991= 9984

第五次循环:n=9984   n=n&(n-1)=9984&9983= 9728

第六次循环:n=9728   n=n&(n-1)=9728&9727= 9216

第七次循环:n=9216   n=n&(n-1)=9216&9215= 8192

第八次循环:n=8192   n=n&(n-1)=8192&8191= 0


我们可以观察到,该数按位与下一位,有几个1就可以进行几次。据此,我们可以写出代码:

int NumberOf1(int n)
{
  int count = 0;
  while(n)
  {
    n = n&(n-1);
    count++;
  }
  return count;
}

求两个数二进制中不同位的个数

1. 先将m和n进行按位异或,此时m和n相同的二进制比特位清零,不同的二进制比特位为1

2. 统计异或完成后结果的二进制比特位中有多少个1即可

int calc_diff_bit(int m, int n)
{
  int tmp = m^n;
  int count = 0;
  while(tmp)
  {
    tmp = tmp&(tmp-1);
    count++;
  }
  return count;
}

喝汽水问题

喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以喝多少汽水(编程实现)。

这个题目,同样有两个解法。第一种方法,让我们画图来理解:

以五瓶汽水为例子,演示一下。

当换汽水不能再执行的条件,也就是 只剩下一个空瓶子的时候。同样的,我们可以总结出来规律:empty=money;(一开始空的罐子等于花了多少钱)total=total+empty/2;(换得的饮料总数等于花的钱除以一开始花钱买的加上用空罐子换取的,empty=empty/2+empty%2;(比如说5瓶,能换2瓶喝了,剩下就是喝了的2个剩的空瓶和没法换的1个空瓶)

方法一:

#include<stdio.h> 
int main()
{
  int money;
  scanf("%d", &money);
  int total = money; 
  int empty = money; 
  while (empty > 1) {
    total = total + empty / 2;
    empty = empty / 2 + empty % 2;
  }
  printf("%d\n", total); 
  return 0;
}

还有一个方法,就是采取等差数列的求法:

方法二:

#include<stdio.h>
int main()
{
  int money;
  scanf("%d", money);
  int total;
  if (money <= 0)
  {
    printf("请喝西北风");
  }
  else {
    money = total * 2 - 1;
  }
  printf("%d", total);
  return 0;
}

打印菱形

我们可以将上半部分和下半部分分开打印,首先画出总表,观察规律:

上半部分共有7行

由此可以总结出:空格个数等于line-1-i,星号个数等于 2*i+1。

再看下半部分:

星号个数为(line-1-i)*2-1,空格个数为i+1。据此我们就可以打印出此题的代码:

#include<stdio.h>
int main()
{
  int line = 7;
  for (int i = 0; i < line; i++)//打印上半部分
  {
    for (int j = 0; j < line - 1 - i; j++)
    {
      printf(" ");
    }
    for (int j = 0; j < 2 * i + 1; j++) 
    {
      printf("*");
    }
    printf("\n");
  }
  for (int i = 0; i < line - 1; i++)
  {
    for (int j = 0; j < i + 1; j++)
    {
      printf(" ");
    }
    for (int j = 0; j < (line - 1 - i) * 2-1; j++)
    {
      printf("*");
    }
    printf("\n");
  }
  return 0;
}

打印奇数位和偶数位

打印水仙花数

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

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

要打印水仙花数,我们要知道位数,并且把要验证的每一位都取出来。

#include<stdio.h>
#include<math.h>
int main() {
  for (int i = 1; i <= 100000; i++)
  {
    int count = 0;
    int tmp = i;
    while (tmp != 0) {
      count++;
      tmp /= 10;
    }
    tmp = i;
    int sum = 0;
    while (tmp != 0) {
      sum += pow(tmp % 10, count);
      tmp /= 10;
    }
    if(i == sum) {
      printf("%d\n", i);
    }
  }
  return 0;
}

求和

求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,

例如:2+22+222+2222+22222

#include<stdio.h>
#include<math.h>
int main() {
  int n = 5;
  int a = 2;
  int tmp = 0;
  int sum = 0;
  for (int i = 0; i < n; i++) 
  {
    tmp = tmp * 10 + a;
    sum += tmp;
  }
  printf("%d",sum);
  return 0;
}

找只出现一次的数字

相同的数字异或都为0,0和任意数字异或都为其本身。据此,我们写出如下代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
  int arr[] = { 1,2,3,2,1 };
  int len = sizeof(arr) / sizeof(arr[0]);
  int sum = 0;
  for (int i = 0; i < len; i++)
  {
    sum ^= arr[i];
  }
  printf("%d", sum);
  return 0;
}

打印奇数位和偶数位

获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列

只要末位&1,就能知道最后一位是0还是1,如果是1,那么得到的是1,反之,则为0。

偶数位,也就是最左边的数字,应该右移31位,最后一个偶数应该右移一位,所以限制条件应当是i>=2。

#include<stdio.h>
void function(int n)
{
  for (int i = 31; i >= 1; i-=2)//偶数位
  {
    printf("%d", (n >> i)&1);
  }
  printf("\n");
  for (int i = 30; i >= 0; i -= 2)//奇数位
  {
    printf("%d", (n >> i)&1);
  }
  printf("\n");
}
int main()
{
  function(9);
  return 0;
}

递归

斐波那契数列

#include<stdio.h>
int fabonacci(int n)
{
  if (n <= 1) return n;
  else return fabonacci(n - 1) + fabonacci(n - 2);
}
int main()
{
  int n = 10;
  printf("第%d个斐波那契数是%d", n, fabonacci(n));
  return 0;
}

递归实现n的k次方

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int fact(int n,int k)
{
  if (k==1) return n;
  else return n*fact(n,k-1);
}
int main()
{
  int n ;
  int k;
  printf("请输入n和k的值");
  scanf("%d %d", &n, &k);
  printf("%d", fact(n, k));
  return 0;
}

计算一个数的每位之和(递归实现)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int factsum(int n)
{
  if (n<10) return n;
  else return n%10+factsum(n/10);
}
int main()
{
  int n ;
  printf("请输入n");
  scanf("%d", &n);
  printf("%d", factsum(n));
  return 0;
}

递归方式实现打印一个整数的每一位

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void print(int n)
{
  if (n < 10) {
    printf("%d ", n);
  }
  else {
    print(n/10);
    printf("%d ", n % 10);
  }
}
int main()
{
  print(123);
  return 0;
}
相关文章
|
2月前
|
算法 搜索推荐 程序员
第四十六练 请以递归方式实现计算整数列表的和
第四十六练 请以递归方式实现计算整数列表的和
24 2
|
8月前
|
Linux 测试技术 数据处理
R语言丨根据VCF文件设计引物,自动识别两样本差异SNP位点,调用samtools获取上下游参考序列,快速得到引物序列
R语言丨根据VCF文件设计引物,自动识别两样本差异SNP位点,调用samtools获取上下游参考序列,快速得到引物序列
|
9月前
成信大ENVI_IDL第一周实验测试:数组的简单运算+详细解析
成信大ENVI_IDL第一周实验测试:数组的简单运算+详细解析
51 0
|
10月前
|
C语言
【滴水逆向三期41作业】C语言提取文件PE头部信息
【滴水逆向三期41作业】C语言提取文件PE头部信息
|
11月前
编写代码实现:单词计数。对文档中的单词计数(注意:不包括符号),并把单词计数超过3的结果进行保存。
编写代码实现:单词计数。对文档中的单词计数(注意:不包括符号),并把单词计数超过3的结果进行保存。
|
人工智能 C语言
对C语言作业中的一道较难题的思考记录
刚开始非常害怕,为什么4个变量就可以完成要求,后来去凑答案可以运行,最后又去寻求大佬们的帮助,终于想明白了这个问题。
25 0
|
算法
重温算法之路径总和
关于二叉树的题目,深度优先和广度优先是最佳首选,其次就是利用hash或者栈的特点结合,也可以快速解决问题,另外还是没有找到之前动态二叉树的网站,估计已经没了,不然更加容易理解。
75 0
重温算法之路径总和
|
监控 JavaScript Java
函数计算是如何工作的|学习笔记
快速学习 函数计算是如何工作的
141 0
|
测试技术
测试用例(包含测经典试点全集图解,强烈建议保存收藏)(二)
测试用例(Test Case)是指对一项特定的软件产品进行测试任务的描述,体现测试方案、方法、技术和策略。其内容包括测试目标、测试环境、输入数据、测试步骤、预期结果、测试脚本等,最终形成文档。简单地认为,测试用例是为某个特殊目标而编制的一组测试输入、执行条件以及预期结果,用于核实是否满足某个特定软件需求。
113 0
测试用例(包含测经典试点全集图解,强烈建议保存收藏)(二)
|
测试技术 数据库
测试用例(包含测经典试点全集图解,强烈建议保存收藏)(一)
测试用例(Test Case)是指对一项特定的软件产品进行测试任务的描述,体现测试方案、方法、技术和策略。其内容包括测试目标、测试环境、输入数据、测试步骤、预期结果、测试脚本等,最终形成文档。简单地认为,测试用例是为某个特殊目标而编制的一组测试输入、执行条件以及预期结果,用于核实是否满足某个特定软件需求。
395 1
测试用例(包含测经典试点全集图解,强烈建议保存收藏)(一)