目录
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();
}
}
}