21级青藤工作室第一次考核答案
一、
一个小球距地面 10 米处垂直落下,当小球触底反弹时,由于受到神秘力量 影响,小球的初速度瞬间增大,使得每次反弹的高度都为原高度的 2 倍。请编 写一个函数,在误差合理范围内求前 n 次反弹时向上的初速度(分别输出每一 次的速度)。可使用 sqrt 函数 。不计空气阻力,g 取 10m/s^2 (0 < n < 101 ),n 为整数。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double MagicBall(int n);
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
printf("小球第 %d 次反弹时的速度为:%lf\n", i, MagicBall(i));
}
system("pause");
return 0;
}
double MagicBall(int n)
{
double hight = 10; //小球高度
int count = n; //小球要反弹的次数
while (n)
{
hight *= 2.0; //计算第 n 次反弹结束时小球距离地面的高度
n--;
}
double t = sqrt(2 * hight / 10 ); // 1/2 * g * t^2 = s 求 t
double v = 10 * t; // v= g*t
return v;
}
二、
二、给你一个字符串 num ,表示一个大整数。请你在字符串 num 的所有 非空 子字符串 中找出 值最大的奇数 ,并以字符串形式返回。如果不存在奇数,则 返回一个空字符串 “” 。 子字符串 是字符串中的一个连续的字符序列
- 示例 1:
- 输入:num = “52”
- 输出:“5”
- 解释:非空子字符串仅有 “5”、“2” 和 “52” 。 “5” 是其中唯一的奇数。
- 示例 2:
- 输入:num = “4206”
- 输出:""
- 解释:在 “4206” 中不存在奇数。
- 示例 3:
- 输入:num = “35427”
- 输出:“35427”
- 解释:“35427” 本身就是一个奇数。
#include <stdio.h>
#include <stdbool.h>
#define MAX_STR_LEN 64
int read_line(char *dest, int sz);
int main() {
char inp[MAX_STR_LEN];
printf("Tip: Enter empty line to quit.\n");
char dest[MAX_STR_LEN];
printf(">");
int len = read_line(dest, MAX_STR_LEN);
while (dest[0] != '\0') {
bool proceed = false;
for (int i = len - 1; i >= 0; --i) {
if (dest[i] == '1' || dest[i] == '3' || dest[i] == '5' || dest[i] == '7' || dest[i] == '9') {
proceed = true;
dest[i + 1] = '\0';
printf("%s", dest);
break;
}
}
if (!proceed) {
printf("(EMPTY)");
}
printf("\n");
printf(">");
len = read_line(dest, MAX_STR_LEN);
}
return 0;
}
int read_line(char *dest, int sz) {
int pos = 0;
char c = getchar();
while (c != '\n' && c != '\0') {
if (pos < sz - 1) {
dest[pos] = c;
pos++;
}
c = getchar();
}
dest[pos] = '\0';
return pos;
}
三、
三、给定一个字符串,请写一个程序,将该字符串中的空格全部删除。
*提示
: C 语言中的字符串是 char 数组,字符串的结尾为’\0’(该字符不计入字 符串)。
- 你能不创建额外的字符串数组,原地对字符串进行修改吗?
- 示例: 输入:I am a boy
- 输出: Iamaboy
#include <stdio.h>
#include <stdlib.h>
// 程序中容许从用户输入接收的字符串的最大长度
#define MAX_STR_LEN 64
void read_line(char *dest, int sz);
void do_erase_spaces(char dest[]);
int main() {
printf("Tip: Enter empty line to quit.\n");
char dest[MAX_STR_LEN]; // 这个数组用于接收用户输入以及对字符串进行处理
printf(">");
read_line(dest, MAX_STR_LEN); // 读取用户输入的一行字符串,while中的read_line同理
while (dest[0] != '\0') { // 只要输入的字符串不为空就做处理
do_erase_spaces(dest); // 移除字符串的空格
printf("%s\n", dest); // 打印字符串
printf(">");
read_line(dest, MAX_STR_LEN); // 继续读取输入的字符串
}
return 0;
}
// 移除字符串空格的的函数,dest为传入的字符串数组
void do_erase_spaces(char dest[]) {
// 这个算法使用双指针的思想,字符串中的每个字符只扫描一遍
// 扫描的当前位置用下面for循环的scan表示,下一个字符串赋值位置用cpy表示。
// 当扫描字符串时,若当前字符不是空格则需要将当前字符赋值到dest[cpy],并对cpy加1。
// cpy的初始值为0,即代表字符串数组的第一个元素。
// 实际情况下这段代码一定满足cpy<=scan,即对dest[cpy]赋值不会影响到字符串后续位置的扫描。
int cpy = 0;
for (int scan = 0; dest[scan] != '\0'; ++scan) { // 对整个字符串进行扫描
if (dest[scan] != ' ') { // 如果当前字符串不是空格
// 将当前字符复制到dest[cpy],并cpy++,等效于删除空格
dest[cpy] = dest[scan];
cpy++;
}
}
// 循环结束之后cpy代表的数组位置一定会是删除空格后的字符串结尾后一位
// 需要将该位置的数组元素赋值为\0代表字符串结尾,这是C语言字符串的一个规定。
dest[cpy] = '\0';
}
// 读取用户输入的一行字符串,这个函数的实现原理不在本题的讨论范围之内。
void read_line(char *dest, int sz) {
int pos = 0;
char c = getchar();
while (c != '\n' && c != '\0') {
if (pos < sz - 1) {
dest[pos] = c;
pos++;
}
c = getchar();
}
dest[pos] = '\0';
}
四、
这里有一个石头堆为 s,它由宝石 ‘a’ 和石头 ‘b’ 组成。清理工明明要将 这堆石头清理走,以知明明每一次清理都可以从 s 中删除一个回文子序列。 求返回拿走给定石头堆中所有宝石和石头(字符串为空)的最小清理次数。
「子序列」
定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字 符顺序得到,那么这个字符串就是原字符串的一个子序列。
「回文」
定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一 个回文。
- 示例:
- 输入:s = “ababa”
- 输出:1
- 解释:字符串本身就是回文序列,只需要删除一次。
- 输入:s = “abb”
- 输出:2
- 解释:“abb” -> “bb” -> “”. 先删除回文子序列 “a”,然后再删除 “bb”。
#include<stdio.h>
//思路:
//回文子序列不是回文子字符串,比如"aababdaba","aaaaa"就是他的回文子序列。
//也就是顶多删两次,一次全删掉"a",一次全删掉"b"。
//如果是回文字符串,就删一次。
//空字符串就0次。
int MyStrlen(char *src)//求字符串长度的函数,也可以加#include<string.h>头文件,直接使用strlen函数
{
int len = 0;
while(src[len])
{
len++;
}
return len;
}
int removePalindromeSub(char * str){
int length = MyStrlen(str);
if(length == 0)
return 0;
int low = 0, high = length - 1;
while(low < high)//若该循环完美执行完那么该字符串恰好就是一个回文串
{
if(str[low] != str[high])
return 2;//不符合回文串的定义就必须删除2次
low++;
high--;
}
return 1;//恰好是回文串就能1次删除成功
}
int main(){
char str[10]; //str是string的缩写, 即字符串
printf("请输入字符串:");
scanf("%s", str);
/*输入参数是已经定义好的“字符数组名”,
不用加&, 因为在C语言中数组名就代表该数组的起始地址*/
int i = removePalindromeSub(str);
printf("%d",i);
return 0;
}
五、
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的 三个整数,使得它们的和与 target 最不接近。返回这三个数的和。假定每组输 入只存在唯一答案。 例如,给定数组 nums = [-1,2,1,-4], 和 target = 1. 与 target 最不接近的三个数的和为 -3 (-1+1-4=-4)
- 难点:三次去重
- 思路:
1.给数组排序
2.遍历数组,从0遍历到 numsize - 2
3.如果当前的数字等于前一个数字,则跳过这个数
4.如果数字不同,则设置left = i +1 , right = numsize -1 ,查看i ,left, right三个数的和sum,取与target的差值最大的,比较sum比target大还是小,如果比target小,start++,如果比target大,end–
5.返回结果
双指针解法:
#include<stdio.h>
#include<math.h>
void quickSort(int* nums, int first, int end) { //快速排序
int temp, l, r;
if (first >= end) {
return;
}
temp = nums[first];
l = first;
r = end;
while (l < r) {
while (l < r && nums[r] >= temp) {
r--;
}
if (l < r) {
nums[l] = nums[r];
}
while (l < r && nums[l] <= temp) {
l++;
}
if (l < r) {
nums[r] = nums[l];
}
}
nums[l] = temp;
quickSort(nums, first, l - 1);
quickSort(nums, l + 1, end);
}
int threeSumClosest(int* nums, int numsSize, int target) {
int i = 0; //当前数值下标
int res = nums[0] + nums[1] + nums[2]; //和,初始化
if (numsSize < 3 || nums == NULL) {
return NULL;
}
quickSort(nums, 0, numsSize - 1); //排序
for (i = 0; i <= numsSize - 3; i++) {
int left = i + 1; //左指针
int right = numsSize - 1; //右指针
if (i > 0 && nums[i] == nums[i - 1]) { //去重
continue;
}
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (abs(sum - target) > abs(res - target)) { //取最不接近的和
res = sum;
}
if (sum < target) {
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
right--;
}
else if (sum > target) {
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
left++;
}
else {
return sum;
}
}
}
return res;
}