有序数组查找具体数&猜数字&多个字符向中间汇聚&喝汽水

有序数组查找具体数

一、题目概述

在一个指定的有序数组中,查找具体的一个数

二、解题思路

第一种方法:一个指定的有序数组中,查找一个具体的数,我们可以直接遍历,代码看三

第二种方法:二分查找。
二分查找原理:二分查找针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0

  • 针对的是有序的数据集合,无序的不能用二分查找

二分查找如何实现:如果中间值大于查找值,则往数组的左边继续查找,如果小于查找值这往右边继续查找,如下图

三、代码实现

直接遍历
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	int flag = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;

	scanf("%d", &k);

	for (i = 0; i < sz; i++)
	{
		if (arr[i] == k)
		{
			flag = 1;
			printf("找到了,下标是%d", i);
			break;
		}
	}

	if (flag == 0)
	{
		printf("没找到");
	}



	return 0;
}
二分查找(折半查找)
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	int flag = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int k = 0;
	int left = 0;
	int right = sz - 1;
	int mid = 0;


	scanf("%d", &k);

	while (left <= right)
	{
		//mid = (left + right) / 2;
		mid = left + (right - left) / 2;  //(1)
		if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else
		{
			flag = 1;
			printf("找到了,下标是:%d", mid);
			break;
		}
	}

	if (flag == 0)
	{
		printf("找不到。");
	}

	return 0;
}
  • (1)之所以不用注释计算平均值,是因为如果两个数很大,加起来可能会超过整数最大值,就会导致溢出。所以计算两个值的平均值,只需要计算右边比左边多出来的差值,再把一半给left即可。

猜数字游戏

一、题目概述

随机生成1-100数字,玩家通过猜大猜小得到正确答案

二、解题思路

要完成猜数字游戏,就要先学习随机数知识

1.rand

C语言提供了一个函数rand,可以生成随机数,函数原型如下:

int rand(void);

rand函数会返回一个伪随机数,这个随机数的范围是0-RAND_MAX之间,RNAD_MAX的大小是依赖编译器实现的,大部分是32657
rand函数需要包含头文件<stdlib.h>

rand函数返回的是伪随机数,是通过某种算法生成的随机数,rand函数是对一个叫“种子”的基准值进行运算生成的随机数,而rand函数的种子默认值为1,也就是他每次生成的随机数序列是一样的,想要让他生成不一样的随机数序列,就要去改变这个种子
如何去改变种子?用到srand()函数

2.srand

C语言提供了一个函数srand,用来初始化随机数的生成器,函数原型如下:

void srand(unsigned int seed);

seed其实就是种子,我们可以通过改变seed的参数用来设置rand函数生成的随机数的种子。当种子在变化,rand函数生成的随机数序列也会发生变化,也就是说:我们可以在rand函数调用之前来调用srand函数,通过改变种子去改变rand函数的随机数序列

但是如果种子也需要随机,才能获得rand的随机数序列,就显得有点奇怪,我们到底应该选用什么来作为我们的种子呢?用time函数

3.time

C语言提供了一个函数time,用来通过使用程序运行的时间作为种子,因为时间每时每刻都在变化 函数原型如下

time_t time(time_t* timer)

time 函数会返回当前的日历时间,其实返回的是1970年1月1日0时0分0秒到现在程序运行时间之间的差值,单位是秒。返回的类型是time t类型的,time t类型本质上其实就是32位或者64位的整型类型(本质上是int类型或者是long long类型)。

time函数的参数timer如果是非NULL的指针的话,函数也会将这天返回的差值放在timer指向的内存中带回去。
如果 timer 是NULL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做: 时间戳

时间戳:表示某一刻的时间

time函数的时候需要包含头文件: time.h

如何用time函数返回时间戳?我们可以

time(NULL);//调用time函数返回时间戳,这里没有返回值

这个时候,我们就知道如何随机生成数字了,那么我们应该如何设置随机数的范围呢?

若生成0-99之间的随机数

rand() % 100;//余数的范围是99

如果要生成1-100之间的随机数

rand()%100+1//%100余数是0~99,+1 = 1~100

如果生成100~200的随机数

100 + rand()%(200-100+1)//余数的范围是0~100,加100是100~200

如果我们要生成a~b的随机数,方法如下:

a + rand() % (b - a + 1);

b-a只是公式

三、源码剖析

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void menu()
{
	printf("**********************\n");
	printf("********1.play********\n");
	printf("********0.exit********\n");
	printf("**********************\n");

}

void game()
{
	int guess = 0;
	int ret = rand() % 100 + 1;
	while (1)
	{
		scanf("%d", &guess);

		if (guess > ret)
		{
			printf("猜大了\n");
		}
		else if (guess < ret)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("恭喜你猜对了\n");
			break;
		}

	}
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//(1)

	do
	{
		menu();

		printf("请选择:");

		scanf("%d", &input);

		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);

	return 0;
}
  • (1)time(NULL)直接返回差值,因为srand函数返回的是unsigned int类型,所以time要强制类型转换成unsigned int

搞一个有挑战次数的

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void menu()
{
	printf("**********************\n");
	printf("********1.play********\n");
	printf("********0.exit********\n");
	printf("**********************\n");

}

void game()
{
	int guess = 0;
	int ret = rand() % 100 + 1;
	int count = 0;

	printf("请选择挑战次数:");
	scanf("%d", &count);

	while (1)
	{
		printf("你还有%d次机会\n", count);
		printf("请开始猜数字:");
		scanf("%d", &guess);

		if (guess > ret)
		{
			printf("猜大了\n");
		}
		else if (guess < ret)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("恭喜你猜对了\n");
			break;
		}
		count--;

		if (count == 0)
		{
			printf("挑战失败,正确答案是%d\n", ret);
		}

	}
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));

	do
	{
		menu();

		printf("请选择:");

		scanf("%d", &input);

		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);

	return 0;
}

多个字符从两端移动,向中间汇聚

一、题目概述

多个字符从两端移动,向中间汇聚

二、解题思路

创建两个数组,用有字的数组的一前一后去替换第二个星号数组,

①创建一个left和right变量,分别初始化为0和strlen(arr) - 1

  • strlen(arr) - 1计算数组的大小,减去1就是数组最后一个元素的下标

②arr1把第一个字符和最后一个字符赋给arr2的第一个字符和最后一个字符,然后打印出来,打印出来之后left++right–,就能实现1变成2,2变成3… right就可以从数组最后一个元素到数组倒数第二个元素,从数组倒数第二个元素–变成数组倒数第三个元素…。不断循环到左边的数大于右边的数,就证明循环结束。

三、源码剖析

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main()
{
	char arr1[] = "yuanshen! qi dong !";
	char arr2[] = "*******************";

	int left = 0;
	int right = strlen(arr1) - 1;

	while (left <= right)
	{
		arr2[right] = arr1[right];
		arr2[left] = arr1[left];
		Sleep(1000);		//(1)
		system("cls");		//(3)
		printf("%s\n", arr2);
		left++;
		right--;
	}
	return 0;

}
  • (1)Sleep()函数是用来休眠的,单位是毫秒,

  • (2)system()函数是执行命令的

喝汽水问题

一、题目概述

喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以喝多少汽水(编程实现)。

二、解题思路

假设我们只买五瓶汽水,那么会得到如下图片:

可以看出,一开始买了多少瓶就会有多少空瓶,然后两个空瓶换一瓶汽水,5个空瓶能换2个,2个汽水就是2个空瓶,(即5/2= 2余1)2汽水还能换一个,1个汽水还有一个空瓶,还余下一个空瓶,剩下的2再换一个汽水,汽水还剩下一个空瓶,如此类推

所以代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int total = 0;
	int money = 0;
	int empty = 0;
	
	scanf("%d", &money);

	total = money;
	empty = money;

	while (empty > 1)
	{
		total += empty / 2;
		empty = empty / 2 + empty % 2;
	}

	printf("%d",total);



	return 0;
}
  • empty只要剩下1个,就无法再换汽水了。

  • 我们来看一下规律,

    6块- 11汽水

    5块 - 9汽水

    3块 - 5汽水

  • 得出公式 汽水= 2 * money - 1

最终的代码如下

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int total = 0;
	int money = 0;
	int empty = 0;
	
	scanf("%d", &money);

	total = money;
	empty = money;

	total = 2 * money - 1;

	printf("%d",total);



	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鹤言o 0 O

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值