C语言简单题目的优化合集(多种解法分享)

简介: C语言简单题目的优化合集(多种解法分享)

前言

近期做简单题的时候,发现有的题不止一种解法,并且有的解法很简便,所以写一篇文章记录一下。

大家在看题目的时候也可以试一试自己能想出几种解法,如果大家觉得自己的解法也很巧妙,欢迎和我交流~

喝汽水

题目:

喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以喝多少汽水。

(在做题时,可以将20换成n)

解法一

直接通过简单的数学计算一下,这是最容易想到也是最直接的解法。

代码如下

int main()
{
  int money = 0;
  int bottle = 0;
  int empty = 0;
  scanf("%d", &money);
  bottle = money;
  empty = money;
  while (empty > 1)
  {
    bottle += empty / 2;
    empty = (empty / 2) + (empty % 2);
  }
  printf("%d\n",bottle);
  return 0;
}

解释

就是喝一次买一次,喝光了再用剩下的空瓶子兑换新的

解法二

int main()
{
  int money = 0;
  int bottle = 0;
  scanf("%d", &money);
  if (money > 0)
    bottle = 2 * money - 1;
  else
    bottle = 0;
  printf("%d\n", bottle);
  return 0;

解释

我们可以发现一个数学规律:

钱数与最终能喝到的饮料数的关系为:

bottle = 2 * money - 1;

利用这个表达式,就可以更简单的求出结果

找1

题目

写一个函数返回参数二进制中 1 的个数。

解法一

int count_num_of_1(unsigned int n)
{
  int count = 0;
  while (n)
  {
    if (n % 2 == 1)
      count++;
    n /= 2;
  }
  return count;
}
int main()
{
  int num = 0;
  scanf("%d", &num);//-1
  int ret = count_num_of_1(num);
  printf("%d\n", ret);
  return 0;
}

很常规也很简单的一种解法,这里就不解释了

解法二

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

解释

使用移位操作符,使用二进制来解题,更直观。

总结

善用操作符可能有时候会简化代码

找不同

题目

两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同

解法一

int count_diff_bit(int m ,int n)
{
  int i = 0;
  int count = 0;
  for (i=0; i<32; i++)
  {
    if (((m >> i) & 1) != ((n >> i) & 1))
      count++;
  }
  return count;
}
int main()
{
  int m = 0;
  int n = 0;
  scanf("%d %d", &m, &n);
  int ret = count_diff_bit(m ,n);
  printf("%d\n", ret);
  return 0;
}

解释

if语句就是判断在同时右移i个bit位之后,二者这是否相同

解法二

int count_diff_bit(int m, int n)
{
  int r = m ^ n;
  int i = 0;
  int count = 0;
  while (r)
  {
    r = r & (r - 1);
    count++;
  }
  return count;
}
int main()
{
  int m = 0;
  int n = 0;
  scanf("%d %d", &m, &n);
  int ret = count_diff_bit(m, n);
  printf("%d\n", ret);
  return 0;
}

解释

两个点异或和while循环中r的计算

异或操作符:对应的二进制位相同为0,相异为1,那m和n的不同的二进制位异或后一定是1

之后数一下r的二进制中1的个数,就是m和n中不同位的个数

因为二进制的数字减1,就一定有一位变为0,所以将r与(r-1)进行按位与操作(&)后即可。

总结

无论是解法一的移位操作还是解法二中的异或操作,其实考察的就是对于操作符是否能熟练运用,个人觉得并无优劣之分,只是分享一下不同的解法。

逆置数组

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

如:

i am student

输出:

tneduts ma i

提示:

下面两种解法,不做比较,但我本人更推荐第二种解法

解法一

#include <stdio.h>
#include <string.h>
int main() {
    char arr[10001] = { 0 };
    gets(arr);
    int len = strlen(arr);
    int i = 0;
    for (i = len - 1; i >= 0; i--)
    {
        printf("%c", arr[i]);
    }
  return 0;
}

解释:

就是正着输入,倒着打印

解法二

int main() {
    char arr[10001] = { 0 };
    gets(arr);
    char* left = arr;
    char* right = arr + strlen(arr) - 1;
    while (left < right)
    {
        char tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    }
    printf("%s\n", arr);
    return 0;
}

解释:

采用双指针的方式,比使用if语句或者其他语句的解法要更高效,但在此就不展示其他解法了。

输出月份天数

输入一个值,输出对应的月份天数,这道题有很多种解法,在此只介绍两种,一种简单解法,一种优化解法。

像使用if语句的解法在此就不引入了,(这种解法有点吓人(捂脸))

解法一

int is_leap_year(int y)
{
    if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))
        return 1;
    else
        return 0;
}
int main()
{
    int y = 0;
    int m = 0;
    while (scanf("%d %d", &y, &m) == 2)
    {
        int d = 0;
        switch (m)
        {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            d = 31;
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            d = 30;
            break;
        case 2:
            d = 28;
        }
        if (is_leap_year(y) && m == 2)
            d++;
        printf("%d\n", d);
    }
    return 0;
}

很简单,在此解释一下多组输入这个问题,因为scanf函数接收数据时,接收一个数据返回值是1,接收两个数据,返回值就是2,所以当输入的数据有两个时,就一直判定。

解法二

int is_leap_year(int y)
{
    if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))
        return 1;
    else
        return 0;
}
int main()
{
    int y = 0;
    int m = 0;
    int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    while (scanf("%d %d", &y, &m) == 2)
    {
        int d = days[m];
        if (is_leap_year(y) && (m == 2))
            d++;
        printf("%d\n", d);
    }
    return 0;
}

解释

使用到了数组,还是比较神奇的一种解法,相较于解法一就简单了一些。

结语

打算新开一个系列,关于题目的多种解法的,因为经常在阅读其他人写的代码的时候,就有一种感觉,这个人怎么写的那么好,他怎么想的。

所以就想开一个专栏关于题目解法的优化的,遇到好题记录一下分享给大家,目前暂定也是一篇文章五道题,目前大都是简单题,慢慢来。


相关文章
|
1月前
|
程序员 C语言
【C语言】LeetCode(力扣)上经典题目
【C语言】LeetCode(力扣)上经典题目
|
1月前
|
算法 搜索推荐 C语言
【C语言】冒泡排序+优化版
【C语言】冒泡排序+优化版
|
3月前
|
存储 编译器 C语言
【C语言】指针练习题目
【C语言】指针练习题目
|
5月前
|
机器学习/深度学习 搜索推荐 程序员
C语言实现个人通讯录(功能优化)-2
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-2
|
5月前
|
存储 C语言 索引
C语言实现个人通讯录(功能优化)-1
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-1
|
4月前
|
存储 编译器 定位技术
结构体数组在C语言中的应用与优化策略
结构体数组在C语言中的应用与优化策略
|
5月前
|
测试技术 C语言
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
45 1
|
5月前
|
C语言
C语言学习记录——操作符习题、算数转换习题,多解法&优解法&单选题
C语言学习记录——操作符习题、算数转换习题,多解法&优解法&单选题
28 1
|
4月前
|
存储 编译器 数据库
结构体数组在C语言中的应用与优化技巧
结构体数组在C语言中的应用与优化技巧
|
6月前
|
算法 编译器 API
C语言易混淆、简单算法、结构体题目练习、常见关键字总结-1
C语言易混淆、简单算法、结构体题目练习、常见关键字总结