【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.1 题目1)

[1.2 题目2](#1.2 题目2)

[1.3 题目3](#1.3 题目3)

[1.4 题目4](#1.4 题目4)

[1.5 题目5](#1.5 题目5)

二、两道算法题

[2.1 至少是其他数字两倍的最大数](#2.1 至少是其他数字两倍的最大数)

[2.1.1 题目理解](#2.1.1 题目理解)

[2.1.2 思路](#2.1.2 思路)

[2.1.3 实现](#2.1.3 实现)

[2.2 两个数组的交集](#2.2 两个数组的交集)

[2.2.1 题目理解](#2.2.1 题目理解)

[2.2.2 思路](#2.2.2 思路)

[2.2.3 报错](#2.2.3 报错)

[2.2.4 实现](#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 循环的次数为( )

cpp 复制代码
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 和实参数组的说明是如下形式,则对函数的调用语句中,正确的是( )

cpp 复制代码
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 实现

代码演示:

cpp 复制代码
//C语言
int dominantIndex(int* nums, int numsSize) {
    if (numsSize == 1) return 0; // 只有一个元素时直接返回下标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;
}

或者说这样的写法(更加好看)------

cpp 复制代码
//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++学得怎么样------

代码演示:

cpp 复制代码
//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 报错

这是博主写的一个失败案例,但博主觉得还可以抢救一下,这应该也是一种思路------

cpp 复制代码
//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型就可以不用管它们了)------

代码演示:

cpp 复制代码
//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))

这个用到了哈希数组的知识,我们还没有介绍过哈希,因此博主还有这样的写法,不用哈希------

cpp 复制代码
//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;
    //遍历nums1
    for (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;
        }
        //检查nums2
        for (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++学得怎么样------

代码演示:

cpp 复制代码
//用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

结语: 感谢大家的阅读,记得给博主"一键四连",感谢友友们的支持和鼓励!

相关推荐
呼啸长风16 分钟前
漫谈散列函数
算法
NAGNIP20 分钟前
彻底搞懂 RoPE:位置编码的新范式
算法
伴杯猫22 分钟前
【ESP32-IDF】高级外设开发3:I2S
c语言·单片机·嵌入式硬件·mcu·物联网·esp32·esp-idf
NAGNIP27 分钟前
一文搞懂位置编码Positional Encoding
算法
Ghost-Face1 小时前
关于模运算
算法
我爱学嵌入式1 小时前
C语言:第18天笔记
c语言·开发语言·笔记
SunnyKriSmile2 小时前
指针实现数组的逆序存放并输出
c语言·算法·排序算法·数组逆序存放
Y4090012 小时前
Java算法之排序
java·数据结构·笔记·算法
sinat_286945192 小时前
AI服务器介绍
服务器·人工智能·算法·chatgpt·transformer
严文文-Chris2 小时前
【大模型量化、蒸馏、剪枝、微调小结】
算法·机器学习·剪枝