C语言-刷题专栏

1、使用折半查找算法,查找一个值

思路:通过下标找到左右范围,在找到中间值,通过对中间值与要找的值比较,看是不是,不是就比较大小,在重新确定左右下标,找中间值。

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int left = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	int right = sz - 1;
	scanf_s("%d", &i);
	while (left<=right)
	{
		int mid = (left + right) / 2;
		if (arr[mid] > i)
		{
			right = mid - 1;
		}
		else if (arr[mid] < i)
		{
			left = mid + 1;
		}
		else
		{
			printf("找到了,下标是:%d", mid);
			break;
		}
	}
	if (left > right)
	{
		printf("没有找到");
	}
	return 0;
}

2、使用冒泡排序对一组数排序

3、变种的水仙花树

要求:变种水仙花树 求0-100000的水仙花数,例:153=1的三次方+5的三次方+3的三次方

思路:
1:先求出得到的每一个数有多少位,使用除10的方法,除10就相当于去掉一位,去掉一位就+1,如果数等于0了,就不用除了,也就+完了。
数一个数有多少位,其实和现实生活一样,一个大袋子有好多苹果,我们一个一个的拿出来,拿出一个,在心里计一个数,当袋子空了,就停止计数,此时就数得了一个袋子里有多少个苹果。
计算一个数有多少位,就相当于计算一个袋子中有多少个苹果,将一位数比作一个苹果,拿出一个苹果,就在心里+1,直到袋子空了,就停止拿。
除10就相当于在袋子里拿苹果,在心里计一个数,就相当于设置一个计数器count,因为除10,可以将一个数的最后一位除去。然后再看数有没有成0,成了0也就意味着被除完了。一直除一直除,直到数为0之后,就停止除。一直拿苹果一直拿,直到袋子空了,就停止拿。
2:得到每一位,使用%10的方法,就能得到每个数的最后一位,在通过/10,去掉已经用完的最后一位,方便%10得到新的最后一位。
%10和/10可以想象成男女搭配,干活不累,/10就是去掉数的,%10就相当于得到数的。
最重要的一点是:%10和/10不能直接对得到的数操作,最后还要用这个数,不能改变数的值,所以对这个数进行拷贝,操作这个数的分身,不能直接对真身操作。

#include<stdio.h>
#include<math.h>
int main()
{
	//变种水仙花树 求0-100000的水仙花数,例:153=1的三次方+5的三次方+3的三次方
	int i = 0;
	for (i = 0;i <= 100000;i++)
	{
		//计算有多少位
		int b = 0;
		//拷贝真身
		b = i;
		int count = 0;
		while (b != 0)
		{
			count++;
			b /= 10;
		}
		//得到每一位,求n次方之和
		//拷贝真身
		b = i;
		int a = 0;
		int sum = 0;
		while (b!=0)
		{
			a = b % 10;
			b = b / 10;
			//将得到的每一个数加到sum上。
			sum = sum + pow(a, count);
		}
		//判断是否相等
		if (i == sum)
		{
			printf("%d\n", i);
		}
	}
	return 0;
}

4、打印菱形

5、求1!+2!+3!+…+10!

思路:分别求出1-10的阶乘,分别加到一个变量里面,所以使用循环语句实现,求每一个数的阶乘,分别产生1-这个数之间的数,在把产生的数分别乘到一个变量中,这是一个循环结构,所以也使用循环语句实现。

#include<stdio.h>
int main()
{
	int i = 0;
	int sum = 0;
	int n = 0;
	scanf_s("%d",&n);
	for (i = 1;i <= n;i++)
	{
		//产生阶乘
		int ret = 1;
		int j = 0;
		for (j = 1;j <= i;j++)
		{
			ret = ret * j;
		}
		//加到sum上
		sum = sum + ret;
	}
	printf("%d", sum);
	return 0;
}

6、求字符串的长度

思路:和数一个袋子里有多少个苹果一样,一次拿一个,拿到一个就在心里+1,直到袋子空了,就不用拿了。
将一个一个的字符比作苹果,每次取出字符,看是不是\0,不是\0,就在计数器+1,直到遇到\0,就停止取。

#include<stdio.h>
int main()
{
	char arr[] = "qwertyuiop";
	int count = 0;
	int i = 0;
	while (arr[i])
	{
		count++;
		i++;
	}
	printf("%d", count);
	return 0;
}

7、将一个字符串拷贝到另一个空间里面

实现字符串拷贝的一个函数
思路:拷贝字符串到另一个空间里面,和将一袋的苹果放到另一个篮子中一样。
找到一个苹果,取出来,在找到篮子中的一个位置,将取出来的苹果放到对应的位置上去,一直重复上面的动作,直到袋子里没有苹果为止。
通过下标或者地址的方式找到字符,在把对应的字符放到对应的位置上去,直到将字符串末尾的\0,放进去之后,就停止放。
注意:字符串拷贝需要将字符串末尾的\0,也放进去。
当循环语句的中的表达式为假时,也就是值为0时,告诉计算机为假,则循环停止;
当拷贝完\0这个字符之后,就停止,并且将\0拷贝到空间之后,存的是0。
这两个最终显示出的结果是一样,所以可以将这个字符

#include<stdio.h>
char* my_strcpy(char* arr1, char* arr2)
{
	char* arr = arr1;
	while (*arr1)
	{
		*arr1 = *arr2;
		arr1++;
		arr2++;
	}
	return arr;
}
int main()
{
	char arr1[20] = "bite hello";
	char arr2[] = "hello bite";
	my_strcpy(arr1, arr2);
	printf("%s", my_strcpy(arr1, arr2));
	return 0;
}

8 、喝汽水问题

喝汽水问题
喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以he多少汽水
思路:
给20元可以换20瓶汽水,喝完之后,有20个空瓶继续换汽水,可以换10瓶,再喝再换,直到手里的空瓶没有两个了就停止。

#include<stdio.h>
int main()
{
	int money = 0;
	scanf_s("%d", &money);
	int empty = 0;
	int drink = 0;
	drink = money;
	empty = money;
	while (empty >= 2)
	{
		drink = drink + empty / 2;
		//统计空瓶还有多少,再去换
		empty = empty / 2 + empty % 2;
	}
	printf("%d", drink);
	return 0;
}

9、将一组数的奇数放在前面,偶数放在后面

思路:
在我的大脑中,我将这个问题想象成了,我高中时期,每个周一要进行升旗仪式,每个班级要站成一队,刚开始是男女穿插着站的,按规定女生站前面,男生站后面,所以班主任从前向后找男生,班长从后向前找女生,找到之后,就让这俩人交换,在继续找,直到班主任和班长相遇,就找完了,就停止。
我将女生比作奇数,男生比作偶数,定义一个左下标去定位偶数,定义一个右下标去定位奇数,找偶数是一个循环过程,直到找到一个偶数,就停止,找奇数也是一个循环,直到找到一个奇数,就停止,分别使用循环语句实现,当这两个下标相遇之后,就停止循环,不相遇,就不停止循环,左下标小于右下标代表不相遇,由于找的时候,左下标和右下标只认偶数和奇数,头比较铁,有可能这俩会找过头了,左下标可能定位到后面的偶数,右下标可能定位到前面的奇数,所以对这两个下标要进行管理,在交换的时候,要进行判断,左下标必须小于右下标,这找到之后,交换,找到之后交换,这也是一个循环,要使用循环语句实现,左下标和右下标相遇就停止循环,左下标和右下标不相遇就不停止循环,左下标小于右下标代表不会相遇。

代码:

#include<stdio.h>
int main()
{
	//将一组数的奇数放在前面,偶数放在后面
	int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	int left = 0;
	int right = sz-1;
	while (left<right)
	{
		//找偶数
		while (left<sz-1 && arr1[left] % 2 != 0)
		{
			left++;
		}
		//找奇数
		while (right>0 && arr1[right] % 2 != 1)
		{
			right--;
		}
		//交换
		if (left < right)
		{
			int tmp = 0;
			tmp = arr1[left];
			arr1[left] = arr1[right];
			arr1[right] = tmp;
		}
	}
	//输出
	int i = 0;
	for (i = 0;i < sz;i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

10、将两个有序序列合并成一个有序序列

#include<stdio.h>
int main()
{
	//将两个有序序列合并成一个有序序列
	int arr1[10] = { 0 };
	int arr2[10] = { 0 };
	int arr3[20] = { 0 };
	int n = 0;
	int m = 0;
	scanf_s("%d%d", &n, &m);
	int i = 0;
	//输入元素
	for (i = 0;i < n;i++)
	{
		scanf_s("%d", &arr1[i]);
	}
	for (i = 0;i < m;i++)
	{
		scanf_s("%d", &arr2[i]);
	}
	//排序
	i = 0;
	int j = 0;
	int k = 0;
	while (i < n && j < m)
	{
		if (arr1[i] < arr2[j])
		{
			arr3[k++] = arr1[i++];
		}
		else if (arr1[i] >= arr2[j])
		{
			arr3[k++] = arr2[j++];
		}
	}
	while (i < n)
	{
		arr3[k++] = arr1[i++];
	}
	while (j < m)
	{
		arr3[k++] = arr2[j++];
	}
	//输出
	for (i = 0;i < (n + m);i++)
	{
		printf("%d ", arr3[i]);
	}
	return 0;
}

判断素数

一个数被判定为素数的规则是什么?
名如其字,朴素!
如果一个数不能被除了1和他本身这个数之间的数整除的话,这个数就会被称为素数。
整除的意思是一个数被除以一个数,能够除干净,余数是0,也就意味着这个数被分解成功,没有余留下一丁点东西,已经空了,0在这时候可以代表为空,所有这个数的余数是0。
这里可以将一个数比作一个零件,这个零件分成四部分,区分这个零件的好坏,如果四个部分都没有毛病就是一个好零件,只要有一个零件有毛病,那它就不是一个好零件,四部分都是有关联的,如果第一部分没有毛病,那第四部分就没有毛病,如果第二部分没有毛病,那第三部分就没有毛病,所以如果检查了前两个零件之后,就不用检查后两个了。
所以可以将数和这些零件联想一下,数和数也是有关联的,如果检查出前面的数,不能使一个数除干净,那与它对应的一个数就不用再检查了,也不会除干净这个数。
所以综上所述,现在我知道有两种方法,可以对判定一个数是否为素数这个工作进行优化:
第一种方法:将这个数对半拆,拆成两半,也就是除以2,只用检查前半部分的数就可以了,后面的数不用再检查,如果前面的数,没有发现问题,那后面的数肯定没有问题。
第二种方法:这个方法比第一种方法效率更高,现在将这个数开平方,这次只用检查开平方的数之前的数就可以了,如果1-开平方之前的数,没有问题,那么开平方之后的数-本身的数,就都没有问题了,不用检查。

第一种方法

 public static void main(String[] args) {
        for (int i = 1; i <=100; i++) {
            int j = 2;
            for (j = 2; j <= i/2; j++) {
                if(i % j == 0){
                    System.out.print(i+"不是素数"+" ");
                    break;
                }
            }
            if(i > i/2)
            {
                System.out.print(i+"是素数"+" ");
            }
        }
    }

第二种方法:

public static void main(String[] args) {
        int count = 0;
        for (int i = 1; i <=100; i++) {
            int j = 2;
            for (j = 2; j <= Math.sqrt(i); j++) {
                if(i % j == 0){
                    System.out.print(i+"不是素数"+" ");
                    count++;
                    break;
                }
            }
            if(j>Math.sqrt(i))
            {
                System.out.print(i+"是素数"+" ");
                count++;
            }
            if((count % 10) == 0){
                System.out.println();
            }
        }
    }
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值