【C语言16天强化训练】从基础入门到进阶:Day 10


 🔥个人主页:艾莉丝努力练剑

❄专栏传送门:《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.2  找到所有数组中消失的数字

2.2.1 题目理解

2.2.2 思路

2.2.3  为什么选择负号标记法?

2.2.4  负号标记法的巧妙之处

2.2.5  与其他方法的对比

结尾


一、五道选择题

1.1  题目1

题干:求函数返回值,传入 -1 ,则在64位机器上函数返回( )

int func(int x)
{int count = 0;while (x){count++;x = x&(x - 1);//与运算} return count;
}

A. 死循环     B. 64     C. 32     D. 16

解析:正确答案就是B选项。

函数 func 的作用是计算整数 x 的二进制表示中1的个数(即汉明重量)。通过循环 x = x & (x - 1) 每次会消除二进制表示中最右边的1,直到 x 变为0。

传入 -1:在64位机器上,-1 的二进制表示是所有位都是1(即64个1)。因此,循环会执行64次(每次消除一个1),最后返回 count = 64

1.2  题目2

题干:读代码选结果( )

int count = 0;
int x = -1;
while(x)
{count++;x = x >> 1;
}
printf("%d",count)

A. 1     B. 2     C. 32     D. 死循环,没结果

解析:正确答案就是D选项。

这里 x 是带符号整数(默认是 signed int),初始为 -1(二进制所有位为1)。执行右移操作 x = x >> 1 是算术右移(对于负数,高位补1)。因此,无论右移多少次,x 始终不会变为0(因为高位一直补1,保持所有位为1,即始终为-1)。所以循环条件 x 永远为非0,导致死循环。

1.3  题目3

题干:下述赋值语句错误的是( )

A. a = (b = (c = 2 , d = 3))     B. i++     C. a / b = 2     D. a = a < a + 1

解析:正确答案就是C选项。

A. 正确,逗号表达式返回最后一个值(d=3),然后赋值给b,再赋值给a;
B. 正确,自增操作;
C. 错误,a/b是一个表达式(值),不能作为左值被赋值;
D. 正确,先计算a < a+1(恒为真,即1),然后赋值给a。

1.4  题目4

题干:若有 int w=1, x=2, y=3, z=4; 则条件表达 w < x ? w : y < z ? y : z 的值是( )

A. 1      B. 2      C. 3      D. 4

解析:正确答案就是A选项。

题干所给表达式:w < x ? w : y < z ? y : z
结合性:从右到左(条件运算符是右结合),所以等价于:w < x ? w : (y < z ? y : z)

计算:w=1, x=2 -> w<x 为真(1),所以返回 w(即1)
因此w < x ? w : y < z ? y : z的值为1。

1.5  题目5

题干:以下程序运行后的输出结果是( )

int main()
{int a=1,b=2,m=0,n=0,k;k=(n=b<a)&&(m=a);printf("%d,%d\n",k,m);return 0;
}

A. 0,0     B. 0,1     C. 1,0     D. 1,1

解析:正确答案就是A选项。

(1)先计算 n = b<a(即n=2<1,为假,所以n=0);

(2)由于 && 短路:第一个操作数 (n=b<a) 结果为0(假),所以第二个表达式 (m=a) 不会执行(m保持原值0);

(3)k 为整个逻辑与的结果(0)。

因此输出:k=0, m=0。

选择题答案如下:

1.1  B

1.2  D

1.3  C

1.4  A

1.5  A

校对一下,大家都做对了吗?


二、两道算法题

2.1  不用加减乘除做加法

牛客链接:JZ65 不用加减乘除做加法

题目描述:

2.1.1 题目理解

为了解决这个问题,我们需要在不使用加减乘除运算符的情况下实现两个整数的加法。我们可以利用位运算来模拟加法过程。

这道题是接口型的,下面是C语言的模版(如果是IO型就可以不用管它们了)——

2.1.2 思路

C语言思路:

1、算法原理:使用位运算模拟二进制加法。

(1)异或运算(~):得到不考虑进位的和;

(2)与运算 + 左移(& + << 1):得到进位值。

2、迭代过程

(1)每次循环计算当前位的和(不考虑进位)和进位值;

(2)将和赋值给 num1,进位赋值给 num2;

(3)重复直到进位为0。

3、处理负数:由于C语言中使用补码表示负数,该算法同样适用于负数加法。

4、时间复杂度:O(1),因为整数位数固定(通常是32位),最多循环32次。

代码演示:

//C语言实现
/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param num1 int整型* @param num2 int整型* @return int整型*/
int Add(int num1, int num2) 
{while (num2 != 0){int sum = num1 ^ num2;int carry = (num1 & num2) << 1;num1 = sum;num2 = carry;}return num1;
}

时间复杂度O(1)

空间复杂度O(1)

博主这里再展示一下完整的C语言代码,包含了测试用例——

代码演示:

//完整C语言代码
#include <stdio.h>int Add(int num1, int num2) 
{while (num2 != 0) {int sum = num1 ^ num2;int carry = (num1 & num2) << 1;num1 = sum;num2 = carry;}return num1;
}int main() 
{// 测试用例printf("1 + 2 = %d\n", Add(1, 2));      // 输出: 3printf("0 + 0 = %d\n", Add(0, 0));      // 输出: 0printf("5 + 7 = %d\n", Add(5, 7));      // 输出: 12printf("-1 + 1 = %d\n", Add(-1, 1));    // 输出: 0printf("10 + -5 = %d\n", Add(10, -5));  // 输出: 5return 0;
}

时间复杂度O(1)

空间复杂度O(1)

我们学习了C++之后也可以尝试用C++来实现一下,看看自己前段时间C++学得怎么样——

C++思路:

1、问题分析:题目要求不使用四则运算符号实现加法。我们可以使用位运算来模拟加法的过程。

2、关键观察:二进制加法的每一位可以分解为:

(1)非进位和:使用异或运算(^)得到,即 num1 ^ num2

(2)进位:使用与运算(&)并左移一位得到,即 (num1 & num2) << 1

3、迭代过程:将非进位和与进位相加,直到进位为0。每次迭代都更新非进位和和进位,直到没有进位为止。

代码演示:

//C++实现
class Solution {
public:int Add(int num1, int num2){while (num2 != 0){int sum = num1 ^ num2;int carry = (num1 & num2) << 1;num1 = sum;num2 = carry;}return num1;}
};

时间复杂度:O(1),空间复杂度:O(1)

1、循环条件:当进位(num2)不为0时,继续循环。

2、计算非进位和:使用异或运算 num1 ^ num2 得到当前位的和,不考虑进位。

3、计算进位:使用与运算 num1 & num2 并左移一位得到进位。

4、更新变量:将非进位和赋值给 num1,进位赋值给 num2,进行下一次迭代。

5、返回结果:当进位为0时,num1 即为最终的和,返回 num1

使用位运算模拟二进制加法通过位运算高效地模拟了加法过程,避免了使用四则运算符号。

我们目前要写出来C++的写法是非常考验前面C++的学习情况好不好的,大家可以尝试去写一写,优先掌握C语言的写法,博主还没有介绍C++的算法题,之后会涉及的,敬请期待!

2.2  找到所有数组中消失的数字

力扣链接:448. 找到所有数组中消失的数字

力扣题解链接:负号标记法解决【找到所有数组中消失的数字】问题

题目描述:

2.2.1 题目理解

题目的本质是:在一个长度为 n 的数组中,所有数字理论上都应该在 [1, n] 范围内,但由于某些数字可能重复出现,导致其他数字缺失。我们需要找出所有缺失的数字。

本题中关键的约束条件——

1、数组长度 = n;

2、数字范围 = [1, n];

3、可能有重复数字;

4、需要找出所有缺失的数字。

2.2.2 思路

我们使用负号标记法,时间复杂度为 O(n),空间复杂度为 O(1)(不考虑输出数组):

1、第一次遍历:对于每个数字 nums[i],我们将 nums[abs(nums[i])-1] 标记为负数;

2、第二次遍历:所有仍然为正数的位置 i 表示数字 i+1 在原始数组中不存在。

这道题是接口型的,下面是C语言的模版(如果是IO型就可以不用管它们了)——

代码演示:

//C语言实现——负号标记法
/*** Note: The returned array must be malloced, assume caller calls free().*/
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize) {// 第一次遍历:使用负号标记法for (int i = 0; i < numsSize; i++) {int index = abs(nums[i]) - 1; // 获取对应的索引位置if (nums[index] > 0) {nums[index] = -nums[index]; // 标记为负数表示该数字存在}}// 统计缺失的数字数量int count = 0;for (int i = 0; i < numsSize; i++) {if (nums[i] > 0) {count++;}}// 分配结果数组int* result = (int*)malloc(count * sizeof(int));*returnSize = count;// 第二次遍历:收集缺失的数字int j = 0;for (int i = 0; i < numsSize; i++) {if (nums[i] > 0) {result[j++] = i + 1; // 索引+1就是缺失的数字}}return result;
}

时间复杂度O(n)

空间复杂度O(1)

我们学习了C++之后也可以尝试用C++来实现一下,看看自己前段时间C++学得怎么样——

代码演示:

//C++实现——负号标记法
class Solution {
public:vector<int> findDisappearedNumbers(vector<int>& nums) {int n = nums.size();// 使用负号标记法for (int i = 0; i < n; i++) {int index = abs(nums[i]) - 1; // 获取对应的索引位置if (nums[index] > 0) {nums[index] = -nums[index]; // 标记为负数表示该数字存在}}vector<int> result;// 收集缺失的数字for (int i = 0; i < n; i++) {if (nums[i] > 0) {result.push_back(i + 1); // 索引+1就是缺失的数字}}return result;}
};

时间复杂度:O(n),空间复杂度:O(1)

我们目前要写出来C++的写法是非常考验前面C++的学习情况好不好的,大家可以尝试去写一写,优先掌握C语言的写法,博主还没有介绍C++的算法题,之后会涉及的,敬请期待!

我们可以用几个示例来验证一下——

对于输入 [4, 3, 2, 7, 8, 2, 3, 1]

(1)第一次遍历后数组变为:[-4, -3, -2, -7, 8, 2, -3, -1];

(2)位置4和5(索引从0开始)的值仍为正数,所以缺失的数字是5和6。

负号标记法这种方法高效且不需要额外的空间(除了输出数组),非常适合处理大规模数据。

2.2.3  为什么选择负号标记法?

1、空间效率: 题目要求 O(1) 额外空间(不包括输出数组);

2、时间效率: 需要 O(n) 时间复杂度;

3、利用现有数组: 既然数字范围是 [1, n],我们可以用数组索引本身来记录信息。

2.2.4  负号标记法的巧妙之处

核心思想:用数组的索引位置来记录数字是否存在。

具体操作:

(1)对于数字 x,我们去查看位置 x-1;

(2)如果该位置的值为正,我们就将其标记为负;

(3)这样,最后仍然为正数的位置 i 就表示数字 i+1 不存在。

为什么这样可行?

(1)因为数组索引从 0 到 n-1,正好对应数字 1 到 n;

(2)负号标记不会改变绝对值,所以不影响后续的判断。

2.2.5  与其他方法的对比

方法1:使用哈希表(不适用)

// 需要 O(n) 额外空间,不符合要求
unordered_set<int> seen;
for (int num : nums) seen.insert(num);
for (int i = 1; i <= n; i++) 
{if (!seen.count(i)) result.push_back(i);
}

方法2:排序后遍历(不最优)

// 时间复杂度 O(n log n),空间复杂度 O(1) 但修改了原数组
sort(nums.begin(), nums.end());
// 然后遍历检查缺失数字

方法3:负号标记法(最优)

1、时间复杂度: O(n) - 两次遍历;

2、空间复杂度: O(1) - 原地修改,无需额外空间;

3、保持信息: 通过负号标记,既记录了存在性,又保留了原始值的绝对值。


结尾

本文内容到这里就全部结束了,希望大家练习一下这几道题目,这些基础题最好完全掌握!

往期回顾:

【C语言16天强化训练】从基础入门到进阶:Day 9

【C语言16天强化训练】从基础入门到进阶:Day 8

【C语言16天强化训练】从基础入门到进阶:Day 7

【C语言16天强化训练】从基础入门到进阶:Day 6

【C语言16天强化训练】从基础入门到进阶:Day 5

【C语言16天强化训练】从基础入门到进阶:Day 4

【C语言16天强化训练】从基础入门到进阶:Day 3

【C语言16天强化训练】从基础入门到进阶:Day 2

【C语言16天强化训练】从基础入门到进阶:Day 1

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/94456.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/94456.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算与云原生技术探索

&#x1f31f; Hello&#xff0c;我是蒋星熠Jaxonic&#xff01; &#x1f308; 在浩瀚无垠的技术宇宙中&#xff0c;我是一名执着的星际旅人&#xff0c;用代码绘制探索的轨迹。 &#x1f680; 每一个算法都是我点燃的推进器&#xff0c;每一行代码都是我航行的星图。 &#x…

STM32之ADC详解

一、ADC概述 ADC&#xff08;模拟量转数字量转换器&#xff09;&#xff0c;在 STM32 开发中&#xff0c;利用 ADC 端口的电压数据&#xff0c;转换为对应的具体数字量数据内容。可通过 ADC 方式获取常用数据内容有&#xff1a; 光敏电阻、电池电量、油箱油量 ADC 转换…

深入理解计算机网络:从基础到应用的全面解析

标题&#xff1a;深入理解计算机网络&#xff1a;从基础到应用的全面解析 引言 计算机网络已经渗透到我们生活的方方面面。从家庭Wi-Fi到全球互联网&#xff0c;我们每天都在通过各种设备进行数据交换。本文将带领你走进计算机网络的世界&#xff0c;深入探讨网络的基础知识、常…

以结构/序列/功能之间的关系重新定义蛋白质语言模型的分类:李明辰博士详解蛋白质语言模型

上海交通大学第三届「AI for Bioengineering 暑期学校」于 2025 年 8 月 8—10 日正式开启。本次暑期学校汇聚了自全球 70 余所高校、 10 余所科研机构及 10 余家行业领军企业的 200 余位青年才俊、科研学者和产业代表&#xff0c;共同聚焦于人工智能&#xff08;AI&#xff09…

【大语言模型 15】因果掩码与注意力掩码实现:深度学习中的信息流控制艺术

【大语言模型 15】因果掩码与注意力掩码实现&#xff1a;深度学习中的信息流控制艺术 关键词&#xff1a;因果掩码、注意力掩码、下三角掩码、Padding掩码、序列建模、GPT解码器、BERT编码器、批量处理优化、自回归语言模型、信息流控制 摘要&#xff1a;在Transformer架构中&a…

大型电动化工程机械设备智能施工试验场的网络设计方案

随着工程机械设备逐步迈向智能化、电动化和无人化&#xff0c;传统施工试验场已经难以满足现代化施工设备的研发、测试和验证需求。为了适应这一趋势&#xff0c;建设一个基于高性能网络架构的大型智能施工试验场成为关键。本文将从网络架构、设备选型和功能实现等方面&#xf…

SPMI总线协议(一)

1、简单说明 系统电源管理接口( System Power Management Interface简称SPMI)是一种双线串行接口,用于连接片上系统(SoC)处理器系统的集成电源控制器(PC)与一个或多个电源管理集成电路(PMIC)电压调节系统。SPMI 使系统能够使用单个 SPMI 总线动态调整 SoC 内部电压域的…

数据存储的思考——从RocketMQ和Mysql的架构入手

数据存储是后台服务系统永远绕不开的知识 笔者希望能够从宏观的角度出发&#xff0c;思考数据存储系统的共性和设计方案&#xff0c;尝试从Mysql和RocketMQ的角度去思考谈谈系统存储架构的设计哲学 前置的知识 什么是RocketMQ、什么是Mysql&#xff0c;他们对于后端系统的主用…

MySQL 面试题系列(二)

目录1: SQL 中常见的 JOIN 类型有哪些&#xff1f;请分别说明其连接逻辑和适用场景。2: UNION 和 UNION ALL 有什么区别&#xff1f;它们各自的适用场景是什么&#xff1f;3: 什么是视图 (View)&#xff1f;它的作用和优缺点是什么&#xff1f;4: 什么是索引 (Index)&#xff1…

PostgreSQL诊断系列(2/6):锁问题排查全攻略——揪出“阻塞元凶”

&#x1f517; 接上一篇《PostgreSQL全方位体检指南》&#xff0c;今天我们深入数据库的“神经系统”——锁机制&#xff0c;解决最令人头疼的“卡顿”问题。 你是否经历过&#xff1a; 某个SQL执行着就不动了&#xff1f;应用界面卡在“加载中”&#xff1f;UPDATE 语句迟迟不…

crc16是什么算法

核心概念​CRC16​ 是一种循环冗余校验算法&#xff0c;属于哈希函数的一种。它的核心目的是检测数据的错误&#xff0c;通常用于数字网络和存储设备中&#xff0c;来验证数据在传输或存储后是否依然完整、无误。你可以把它想象成一个数据的“指纹”或“摘要”。发送方计算出一…

Day8--HOT100--160. 相交链表,206. 反转链表,234. 回文链表,876. 链表的中间结点

Day8–HOT100–160. 相交链表&#xff0c;206. 反转链表&#xff0c;234. 回文链表&#xff0c;876. 链表的中间结点 每日刷题系列。今天的题目是力扣HOT100题单。 链表题目。 160. 相交链表 思路【我】&#xff1a; 1&#xff0c;计算链表长度 2&#xff0c;令A为较短链&am…

Rust面试题及详细答案120道(58-65)-- 集合类型

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

Horse3D游戏引擎研发笔记(八):在QtOpenGL环境下,按需加载彩虹四边形的顶点属性 (Unity、Unreal Engine、Three.js与Godot)

在上一篇博客中&#xff0c;我们探讨了如何在QtOpenGL环境下使用改进的Uniform变量管理方式绘制多彩四边形。本文将延续这一主题&#xff0c;深入探讨如何在QtOpenGL环境下按需加载彩虹四边形的顶点属性。这一功能是Horse3D引擎渲染系统的重要组成部分&#xff0c;旨在实现灵活…

模块化设计+微米级精度,GelSight Modulus 触觉型3D轮廓仪深入检测“盲区”

当航空航天工程师在精密舱体中搜寻微米级缺陷&#xff0c;汽车检查员在车间复杂结构里排查隐患&#xff0c;能源领域创新者尝试突破检测边界时&#xff0c;深耕视触觉 3D 显微技术的企业——GelSight&#xff0c;正以全新研发的GelSight Modulus触觉型3D轮廓仪&#xff08;简称…

Pytorch安装详细步骤

第一步&#xff1a;检查显卡支持的的CUDA版本 1.打开NVIDIA控制面板 首先鼠标右击桌面-显示更多选项-NVIDIA控制面板-点击弹出界面右上角的(系统信息)-点击弹出界面的(组件) 2.查看驱动版本 打开系统信息 点击组件,查看 以观测到红色方框内的信息可以看到(NVIDIA CUDA 13.0.…

2025职场进阶:低门槛技能实用手册

每到年初&#xff0c;都会有人问&#xff1a;如果只能投入有限的时间与预算&#xff0c;先考哪一两本证书更划算&#xff1f;本文把近两年的岗位需求、学习可获得性与花费周期做了综合权衡&#xff0c;给出一个以“先提升通用能力&#xff0c;再叠加行业资质”为主线的组合方案…

SDC命令详解:使用set_timing_derate命令进行约束

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 目录 指定降额比例 指定降额对象列表/集合 指定沿 指定最大、最小条件 指定早、晚条件 指定路径的类型 指定降额类型 指定约束 指定增量 写在最后 由于制造…

C++语言程序设计——03 进制ASCII码

目录一、进制表示与转换&#xff08;一&#xff09;不同进制表示&#xff08;二&#xff09;进制转换方法二、ASCII 码&#xff08;一&#xff09;ASCII 码表&#xff08;二&#xff09;ASCII 码转换&#xff08;三&#xff09;大小写英文字母转换【总结&#xff1a;如何记忆AS…

AtCoder Beginner Contest 420-Toggle Maze

题目描述 有一个 H行 W 列的网格。用 (i,j) 表示位于第 i 行&#xff08;从上往下数&#xff09;第 j 列&#xff08;从左往右数&#xff09;的格子。每个格子的状态用字符 Ai,j表示&#xff0c;含义如下&#xff1a; . &#xff1a;空格子。 #’ &#xff1a;障碍格子。 S &am…