【C语言16天强化训练】从基础入门到进阶:Day 6
🔥个人主页:艾莉丝努力练剑
❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、洛谷刷题、C/C++基础知识知识强化补充、C/C++干货分享&学习过程记录
🍉学习方向:C/C++方向学习者
⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平
前言:距离我们学完C语言已经过去一段时间了,在学习了初阶的数据结构之后,博主还要更新的内容就是【C语言16天强化训练】,之前博主更新过一个【C语言刷题12天IO强训】的专栏,那个只是从入门到进阶的IO模式真题的训练。【C语言16天强化训练】既有IO型,也有接口型。和前面一样,今天依然是训练五道选择题和两道编程算法题,希望大家能够有所收获!
目录
正文
一、五道选择题
1.1 题目1
1.2 题目2
1.3 题目3
1.4 题目4
1.5 题目5
二、两道算法题
2.1 至少是其他数字两倍的最大数
2.1.1 题目理解
2.1.2 思路
2.1.3 实现
2.2 两个数组的交集
2.2.1 题目理解
2.2.2 思路
2.2.3 报错
2.2.4 实现
结尾
正文
一、五道选择题
1.1 题目1
题干:以下叙述中正确的是( )
A. 只能在循环体内和switch语句体内使用break语句
B. 当break出现在循环体中的switch语句体内时,其作用是跳出该switch语句体,并中止循环体的执行
C. continue语句的作用是:在执行完本次循环体中剩余语句后,中止循环
D. 在while语句和do-while语句中无法使用continue语句
解析:答案是B选项。
只有B选项“当break出现在循环体中的switch语句体内时,其作用是跳出该switch语句体,并中止循环体的执行”的叙述是正确的。
1.2 题目2
题干:下列 for 循环的次数为( )
for(int i = 0 ; i || i++ < 5;);
A. 0 B. 5 C. 1 D. 无限
解析:答案是D选项。
循环条件为:i || i++ < 5;
1、第一次循环:i = 0,条件为 0 || i++ < 5;
(1)先计算 i++ < 5 : i = 0 < 5 为真,然后i自增为1;
(2)条件变为0 || 真 = 真,进入循环体(空语句)。
2、第二次循环:i = 1,条件为 1 || i++ < 5;
(1)由于 || 的短路特性,第一个操作数i = 1为真,直接判定整个条件为真;
(2)i++ < 5 不会被执行,i保持为1。
3、后续所有循环:i 始终为1(从未自增),条件1
||
...
永远为真。
因此,这是一个无限循环。
关键点:
1、
||
运算符的短路特性:当左边为真时,右边表达式不会执行;2、i 初始化为0后,第一次循环后变为1,之后永远为1(因为i++ < 5;不再执行);
3、条件1
||
...
永远为真。
因此我们选择D选项.无限。
1.3 题目3
题干:以下描述中正确的是( )
A. 由于do-while循环中循环体语句只能是一条可执行语句,所以循环体内不能使用复合语句
B. do-while循环由do开始,用while结束,在while(表达式)后面不能写分号
C. 在do-while循环体中,不一定要有能使while后面表达式的值变为零("假")的操作
D. do-while循环中,根据情况可以省略while
解析:答案是C选项。
A错误:do-while循环体内可以使用复合语句(即用花括号{}括起来的多条语句);
B错误:do-while循环在while(表达式)后面必须写分号(这是语法要求);
C正确:do-while循环体内不一定需要有能使表达式变为假的操作,循环可能通过break、return等其他方式终止,或者根本就是无限循环;
D错误:while是do-while循环的语法组成部分,不能省略。
正确选项是C选项。
1.4 题目4
题干:设函数 fun 和实参数组的说明是如下形式,则对函数的调用语句中,正确的是( )
void fun(char ch,float x[]);
float a[10];
A. fun("asd" , a[]); B. fun('x' , A); C. fun('68' , 2.8); D. fun(32 , a);
解析:答案是D选项。
函数声明为void fun(char ch,float x[]);,需要两个参数:一个char类型,一个float数组(实际传递的是数组首地址),我们分别来看四个选项——
A. fun("asd" , a[]); 错误:第一个参数应为char(不能是字符串),第二个参数不应带 [ ];
B. fun('x' , A); 错误:x' 不是合法字符 (应为单引号括起的字符),A未定义 (应为数组a) ;
C. fun('68' , 2.8); 错误:68' 不是合法字符(应为 '68' ,但多字符常量非法),第二个参数应为数组地址而非浮点数;
D. fun(32 , a); 正确:32是int类型(可自动转换为char),a是float数组名(传递首地址,符合float x[]要求)。
1.5 题目5
题干:在c语言中,一个函数不写返回值类型,默认的返回类型是( )
A. int B. char C. void D.都不是
解析:答案是A选项。
在C语言中,如果一个函数没有明确声明返回类型,编译器默认其返回类型为int(这是传统C语言的规定,但现代C标准建议避免这种写法,因为C99及以上标准要求明确声明类型)。因此正确答案是A. int。
选择题答案如下:
1.1 B
1.2 D
1.3 C
1.4 D
1.5 A
校对一下,大家都做对了吗?
二、两道算法题
2.1 至少是其他数字两倍的最大数
链接:747. 至少是其他数字两倍的最大数
力扣题解链接:遍历数组找到最大值的下标解决
题目描述:
2.1.1 题目理解
在一个整数数组中,找到最大值并检查它是否至少是其他所有数字的两倍。如果是,返回最大值的下标;否则返回-1。
核心要点:
(1)数组中有唯一最大值;
(2)需要验证:最大值 ≥ 2 × 其他任意数字;
(3)注意边界情况(如只有一个元素)。
这道题是接口型的,下面是C语言的模版(如果是IO型就可以不用管它们了)——
2.1.2 思路
1、首先遍历数组找到最大值的下标;
2、再次遍历数组,检查最大值是否至少是其他每个数字的两倍;
3、如果所有其他数字都满足条件,返回最大值下标;否则返回-1。
2.1.3 实现
代码演示:
//C语言
int dominantIndex(int* nums, int numsSize) {if (numsSize == 1) return 0; // 只有一个元素时直接返回下标0int maxIndex = 0;// 找到最大值的下标for (int i = 1; i < numsSize; i++) {if (nums[i] > nums[maxIndex]) {maxIndex = i;}}// 检查最大值是否至少是其他所有数字的两倍for (int i = 0; i < numsSize; i++) {if (i != maxIndex && nums[maxIndex] < 2 * nums[i]) {return -1;}}return maxIndex;
}
或者说这样的写法(更加好看)——
//C语言——自己实现
int dominantIndex(int* nums, int numsSize) {if (numsSize == 0){return 0;}
int maxIndex = 0;
//找到下标
for (int i = 1; i < numsSize; i++)
{if (nums[i] > nums[maxIndex]){maxIndex = i;}
}
//确认是否至少是其他数字两倍的最大数
for (int i = 0; i < numsSize; i++)
{if (i != maxIndex && nums[maxIndex] < 2 * nums[i]){return -1;}
}return maxIndex;
}
时间复杂度:O(n);
空间复杂度:O(1)。
我们学习了C++之后也可以尝试用C++来实现一下,看看自己前段时间C++学得怎么样——
代码演示:
//C++实现
class Solution {
public:int dominantIndex(vector<int>& nums) {if (nums.size() == 1) return 0;int maxIndex = 0;for (int i = 1; i < nums.size(); i++) {if (nums[i] > nums[maxIndex]) {maxIndex = i;}}for (int i = 0; i < nums.size(); i++) {if (i != maxIndex && nums[maxIndex] < 2 * nums[i]) {return -1;}}return maxIndex;}
};
时间复杂度:O(logn),空间复杂度:O(1)。
我们目前要写出来C++的写法是非常考验前面C++的学习情况,大家可以尝试去写一写,优先掌握C语言的写法,博主还没有介绍C++的算法题,之后会涉及的,敬请期待!
2.2 两个数组的交集
链接:349. 两个数组的交集
力扣题解链接:使用哈希数组解决【两个数组的交集的问题】
题目描述:
2.2.1 题目理解
我们简单理解一下:题目想表达的意思就是说给定两个数组,找出它们共有的元素(交集),返回的结果中元素唯一(去重)且顺序不限。
核心要点:
(1)输出结果需要去重;
(2)不考虑输出顺序;
(3)需要高效查找(推荐使用哈希表);
(4)注意空数组情况。
示例说明:
(1)[1,2,2,1] 和 [2,2] 的交集是 [2];
(2)[4,9,5] 和 [9,4,9,8,4] 的交集是 [9,4] 或 [4,9]。
2.2.2 思路
1、使用哈希数组标记nums1中出现的数字;
2、遍历nums2,检查数字是否在nums1中出现过;
3、如果出现过且尚未添加到结果中,则添加到结果数组;
4、避免重复添加:添加后将哈希值标记为2。
2.2.3 报错
这是博主写的一个失败案例,但博主觉得还可以抢救一下,这应该也是一种思路——
//C语言实现——自己的想法:失败了
/*** Note: The returned array must be malloced, assume caller calls free().*/
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {if (nums1Size == 0 || nums2Size == 0){*returnSize = 0;return NULL;}int nums3;int i, j;while (nums1Size <= nums2Size){if (nums1 == nums2){nums3 = nums1 && nums2;}}
}
2.2.4 实现
这道题是接口型的,下面是C语言的模版(如果是IO型就可以不用管它们了)——
代码演示:
//C语言实现——哈希表
#include<stdio.h>
/*** Note: The returned array must be malloced, assume caller calls free().*/
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {// 创建哈希表(简单版本,假设数字范围在0-1000)int hash[1001] = { 0 };int* result = (int*)malloc(sizeof(int) * (nums1Size < nums2Size ? nums1Size : nums2Size));*returnSize = 0;// 标记nums1中出现的数字for (int i = 0; i < nums1Size; i++) {hash[nums1[i]] = 1;}// 检查nums2中的数字是否在nums1中出现过for (int i = 0; i < nums2Size; i++) {if (hash[nums2[i]] == 1) {result[(*returnSize)++] = nums2[i];hash[nums2[i]] = 2; // 标记为已添加,避免重复}}return result;
}
时间复杂度:O(m+n);
空间复杂度:O(min(m+n))。
这个用到了哈希数组的知识,我们还没有介绍过哈希,因此博主还有这样的写法,不用哈希——
//C语言——不用哈希表,用了duplicate去重(AI提供了很大帮助)
/*** Note: The returned array must be malloced, assume caller calls free().*/
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {if (nums1Size == 0 || nums2Size == 0){*returnSize = 0;return NULL;}int max_sameSize = nums1Size < nums2Size ? nums1Size : nums2Size;int* result = (int*)malloc(sizeof(int) * max_sameSize);*returnSize = 0;//遍历nums1for (int i = 0; i < nums1Size; i++){//去重int duplicate = 0;for (int j = 0; j < *returnSize; j++){if (result[j] == nums1[i]){duplicate = 1;break;}}if (duplicate){continue;}//检查nums2for (int k = 0; k < nums2Size; k++){if (nums1[i] == nums2[k]){result[(*returnSize)++] = nums1[i];break;}}}return result;
}
时间复杂度:O(m*n);
空间复杂度:O(min(m+n))。
我们用到了像三目表达式、duplicate查重等等。
我们学习了C++之后也可以尝试用C++来实现一下,看看自己前段时间C++学得怎么样——
代码演示:
//用C++实现
#include <vector>
#include <unordered_set>
using namespace std;class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {unordered_set<int> set1(nums1.begin(), nums1.end());unordered_set<int> result_set;for (int num : nums2) {if (set1.find(num) != set1.end()) {result_set.insert(num);}}return vector<int>(result_set.begin(), result_set.end());}
};
时间复杂度:O(m+n),空间复杂度:O(min(m+n))。
我们目前要写出来C++的写法是非常考验前面C++的学习情况好不好的,大家可以尝试去写一写,优先掌握C语言的写法,博主还没有介绍C++的算法题,之后会涉及的,敬请期待!
结尾
本文内容到这里就全部结束了,希望大家练习一下这几道题目,这些基础题最好完全掌握!
往期回顾:
【C语言16天强化训练】从基础入门到进阶:Day 5
【C语言16天强化训练】从基础入门到进阶:Day 4
【C语言16天强化训练】从基础入门到进阶:Day 3
【C语言16天强化训练】从基础入门到进阶:Day 2
【C语言16天强化训练】从基础入门到进阶:Day 1
结语:感谢大家的阅读,记得给博主“一键四连”,感谢友友们的支持和鼓励!