一些C题目的解答(含暴力解法和部分优化)

本文介绍了如何使用优化算法解决数论问题,如寻找素数和实现二分查找,以及打印空心正方形和空心三角形的图形问题。通过改进暴力求解的方法,利用素数性质和循环技巧提高效率。同时,探讨了打印X形图案的数学规律,展示了从不同角度思考问题的重要性。

目录

一.找素数

①暴力求解

②优化求解

二.二分查找

三.打印空心正方形(来自牛客网)

①.暴力算法

②.稍微优化

四.空心三角形(来自牛客网)

 ①.暴力求解

②优化算法

五.X形图案


一.找素数

1.题目概述

打印出所有在100到200之间的素数

2.解法

①暴力求解

#include<math.h>
#include<stdio.h>
int main()
{
	int i = 0;
	for (i = 100; i <= 200; i++)
	{
		//判断i是否是素数
		int j = 0;
		int flag = 1;
		for (j = 2; j <i; j++)
		{
			if (i % j == 0)
			{
				flag = 0;
				break;
			}
		}
		if (1==flag)
			printf("%d ", i);
	}
	return 0;
}

很多新手,包括我都会这样求解,但其实这种解法,并没优化,即没多考虑素数的性质

②优化求解

要想优化,可以在多想点素数的性质,首先,一个数要是质数,得至少有两个公因数,基于这一点,可以先优化,j的取值范围缩小到sqrt(i).

其次,还要考虑一点,一个数要是质数,那么它必定不是偶数,所以再次对i优化,故可得代码段

#include<math.h>
#include<stdio.h>
int is_prime(int n)
{
	int j = 0;
    //优化2
	for (j = 2; j <= sqrt(n); j++)
	{
		if (n % j == 0)
		{
			return 0;//return 速度优于break
		}
	}
	return 1;
}
int main()
{
	//是素数打印
	int i = 0;
	int count = 0;
    //优化1
	for (i = 101; i <= 200; i += 2)
	{
		if (is_prime(i))
		{
			printf("%d ", i);
			count++;
		}
	}
	printf("\ncount=%d\n", count);
	return 0;
}

二.二分查找

这个题目相对简单,算是复习吧,不过其中唯一的更新算是,有个小技巧,防止溢出

int binary_search(int arr[], int k, int sz)
{
	//先想好怎么用
	int left = 0;
	int right = sz - 1;
	while (left <= right)
	{
		//int mid = (left + right) / 2;不用这个,防止溢出
		int mid = left + (right - left) / 2;
		if (arr[mid] > k)
			//在左边
			right = mid - 1;
		else if (arr[mid] < k)
			left = mid + 1;
		else
			return mid;
	}
		return -1;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 1;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//找到了返回下标
	//找不到返回?不能是0,因为下标有0,返回-1
	int ret=binary_search(arr,k,sz);
	if (ret != -1)
		printf("找到了,下标是:>%d\n", ret);
	else
		printf("找不到\n");
	return 0;
}

三.打印空心正方形(来自牛客网)

题目概述:KiKi学习了循环,BoBo老师给他出了一系列打印图案的练习,该任务是打印用“*”组成的“空心”正方形图案。
输入描述:
多组输入,一个整数(3~20),表示输出的行数,也表示组成正方形边的“*”的数量。
输出描述:
针对每行输入,输出用“*”组成的“空心”正方形,每个“*”后面有一个空格。

①.暴力算法

#include<stdio.h>
int main()
{
    int intm, i, j;
    while (scanf("%d", &intm) != 0)
    {
        for (i = 1; i <= intm; i++)
        {
            printf("* ");
        }
        printf("\n");
        for (i = 1; i <= intm - 2; i++)
        {
            printf("* ");
            for (j = 1; j <= intm - 2; j++)
            {
                printf("  ");
            }
            printf("*\n");
        }
        for (i = 1; i <= intm; i++)
        {
            printf("* ");
        }
        printf("\n");
    }
    return 0;
}

这个真是比较笨的算法了,一行一行打印,不仅低效,而且极耗空间。

②.稍微优化

#include<stdio.h>
int main()
{
    int intm, i, j;
    while (scanf("%d", &intm) != 0)
    {
        for (i = 1; i <= intm; i++)
        {
            for (j = 1; j <= intm; j++)
            {
                if (i == 1 || i == intm || j == 1 || j == intm)
                    printf("* ");
                else
                    printf("  ");
            }
            printf("\n");
        }
    }
    return 0;
}

这个算法就相对高明不少了,首先我们想明白问题的性质,实在n*n的大方块放置'*'和' ',所以我们要想*怎么放置,无非就是 i == 1 || i == intm || j == 1 || j == intm这一部分了。所以这个代码写的就相对不错了。

四.空心三角形(来自牛客网)

题目概述:KiKi学习了循环,BoBo老师给他出了一系列打印图案的练习,该任务是打印用“*”组成的“空心”三角形图案。
输入描述:
多组输入,一个整数(3~20),表示输出的行数,也表示组成三角形边的“*”的数量。
输出描述:
针对每行输入,输出用“*”组成的“空心”三角形,每个“*”后面有一个空格。

 ①.暴力求解

#include<stdio.h>
int main()
{
    int intm,i,j;
    while(scanf("%d",&intm)!=EOF)
    {
        printf("*\n");
        for(i=2;i<=intm-1;i++)
        {
            printf("* ");
            for(j=1;j<=i-2;j++)
            {
                printf("  ");
            }
            printf("*\n");
            
        }
        for(j=1;j<=intm;j++)
        {
            printf("* ");
        }
        printf("\n");
    }
    return 0;
}

这个和上述差不多,也是一行一行敲,特别简陋。

②优化算法

#include<stdio.h>
int main()
{
    int intm,i,j;
    while(scanf("%d",&intm)!=EOF)
    {
        //行
        for(i=1;i<=intm;i++)
        {
            //列
            for(j=1;j<=i;j++)
            {
                if(i>2&&i<intm&&j>1&&j<i)
                {
                    printf("  ");
                }
                else
                    printf("* ");
            }
            printf("\n");
        }
    }
    return 0;
}

这种解法就优化不少,问题我们反过来思考,如果不好考虑'*'怎么放置,不妨反过来思考' ',所谓正难则反。

五.X形图案

题目概述:

KiKi学习了循环,BoBo老师给他出了一系列打印图案的练习,该任务是打印用“*”组成的X形图案。
输入描述:
多组输入,一个整数(2~20),表示输出的行数,也表示组成“X”的反斜线和正斜线的长度。
输出描述:
针对每行输入,输出用“*”组成的X形图案。

 这道题目笔者在之前做了正斜形和反斜形。所以一直想着可以将两者结合求解,但是也没能整出个所以然,而且十分繁琐。所以换个角度,从数学的角度进行思考。方才解惑

int main()
{
    int intm, i, j;
    while (scanf("%d", &intm) != 0)
    {
        //找规律
        for (i = 1; i <= intm; i++)//外循环
        {
            for (j = intm; j >= 1; j--)//内循环
            {
                if (i == j || i + j == intm + 1)
                {
                    printf("*");
                }
                else
                    printf(" ");
            }
            printf("\n");
        }

    }

仔细思考'*'的放置,就可以发现i和j的关系就是在i=j和i+j=intm+1处有'*'.

以上是笔者最近在练习题目的一些小心得。希望各位也能有所收获。如果各位有更优解,欢迎在评论区不吝赐教哦🌹。(笔者是个菜鸟)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值