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 
#include 

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

解释

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

结语

打算新开一个系列,关于题目的多种解法的,因为经常在阅读其他人写的代码的时候,就有一种感觉,这个人怎么写的那么好,他怎么想的。
所以就想开一个专栏关于题目解法的优化的,遇到好题记录一下分享给大家,目前暂定也是一篇文章五道题,目前大都是简单题,慢慢来。

你可能感兴趣的:(C语言错题集,c语言,算法,数据结构)