每日一题——力扣面试题 17.04. 消失的数字

题目链接:https://leetcode.cn/problems/missing-number-lcci/description/

菜鸡做法:

#include <stdlib.h> // 包含标准库头文件,用于内存分配等功能// 函数定义:寻找缺失的数字
int missingNumber(int* nums, int numsSize){// 使用calloc分配内存并初始化为0,大小为numsSize+1,因为缺失的数字在0到numsSize之间int *buffer = calloc(numsSize + 1, sizeof(int));// 遍历数组,标记出现过的数字for(int i = 0; i < numsSize; i++) {buffer[nums[i]] = 1; // 将出现过的数字对应的位置标记为1}// 再次遍历buffer数组,寻找未被标记的位置for(int i = 0; i < numsSize + 1; i++) {if(buffer[i] == 0) { // 如果某位置为0,说明该数字未出现过free(buffer); // 释放之前分配的内存return i; // 返回缺失的数字}}free(buffer); // 释放内存return -1; // 如果所有数字都出现过,按题意这种情况不会发生,返回-1作为错误标志
}

更好的做法:

数学:

我们知道,从0到n的整数之和可以用等差数列求和公式表示为 n * (n + 1) / 2。我们可以先计算出这个和,然后减去数组中所有数字的和,得到的结果就是缺失的数字。

下面是使用求和公式解决这个问题的代码实现,并加上了注释:

#include <stddef.h> // 包含标准库头文件,用于NULL等常量// 函数定义:寻找缺失的数字
int missingNumber(int* nums, int numsSize) {// 计算从0到numsSize的整数之和int total = numsSize * (numsSize + 1) / 2;// 计算数组中所有数字的和int arraySum = 0;for (int i = 0; i < numsSize; i++) {arraySum += nums[i];}// 缺失的数字就是总和减去数组中数字的和int missing = total - arraySum;// 返回缺失的数字return missing;
}

在这个实现中,没有使用额外的内存空间,因此也没有内存释放的操作。这种方法的时间复杂度是O(n),空间复杂度是O(1),是一种比较高效的解决方案。

利用异或的性质:

使用位运算解决寻找缺失数字的问题,可以利用异或运算的性质:一个数和它本身进行异或运算结果为0,一个数和0进行异或运算结果为它本身。因此,可以将数组中的所有数字和0到n(n为数组长度)的所有数字进行异或运算,最终的结果就是缺失的数字。

下面是使用位运算解决这个问题的代码实现:

#include <stddef.h> // 包含标准库头文件,用于NULL等常量// 函数定义:寻找缺失的数字
int missingNumber(int* nums, int numsSize) {int missing = numsSize; // 初始化缺失的数字为数组长度for (int i = 0; i < numsSize; i++) {missing ^= i ^ nums[i]; // 对数组中的数字和0到numsSize的数字进行异或运算}return missing; // 返回缺失的数字
}

在这个实现中,不需要分配额外的内存空间,因此也没有内存释放的操作。这种方法的时间复杂度是O(n),空间复杂度是O(1),比使用额外数组的方法更加高效。

这段代码实现了一个寻找数组中缺失数字的函数,它体现了以下哲学和编程思想:

  1. 对称性与互补性:在数学和哲学中,对称性和互补性是重要的概念。在这个算法中,通过异或运算(XOR)来寻找缺失的数字,利用了异或运算的对称性:任何数与自身异或结果为0,任何数与0异或结果为原数。这种对称性在算法中被用来消除成对的重复数字,从而揭示出缺失的数字。

  2. 简洁性:编程中的一个重要原则是KISS(Keep It Simple, Stupid),即保持代码的简洁性。这个算法通过一个简单的循环和异或运算就解决了问题,没有使用复杂的结构或额外的空间,体现了代码的简洁和高效。

  3. 数学思维:编程常常需要将问题抽象成数学模型来解决。在这个算法中,通过数学上的异或运算来处理数据,体现了数学思维在编程中的应用。

  4. 逻辑推理:算法的设计基于逻辑推理,即通过已知的数学性质(异或运算的性质)来推导出解决问题的方法。这种逻辑推理是编程解决问题的基础。

  5. 优化思想:在编程中,优化是一个重要的考虑因素。这个算法的时间复杂度是O(n),空间复杂度是O(1),是一种时间和空间上都高效的解决方案,体现了优化思想。

  6. 不变性:在函数式编程中,不变性是一个重要的概念,即数据一旦创建就不应该被修改。虽然这个算法不是函数式编程的例子,但它利用了异或运算的不变性来处理数据,即通过异或运算不会改变原始数据,而是产生新的结果。

  7. 抽象与封装:这个算法将寻找缺失数字的逻辑封装在一个函数中,对外部隐藏了实现细节,只提供了一个简单的接口。这种抽象和封装是良好软件设计的基础。

举一反三——异或能够解决哪些问题?:

位异或操作是一种非常有用的位操作,它可以解决多种编程和算法问题,特别是那些涉及成对出现的元素或需要在不使用额外空间的情况下操作数据的问题。以下是一些可以通过位异或操作解决的问题类型及示例:


找出唯一未成对的数字:

在一个数组中,每个元素都成对出现,只有一个元素是唯一的。使用异或可以找到这个唯一的元素,因为相同的数字异或结果为0,任何数字与0异或结果为其本身。

// 函数定义:寻找只出现一次的数字
int singleNumber(int* nums, int numsSize) {int result = 0; // 初始化结果变量为0for (int i = 0; i < numsSize; i++) {result ^= nums[i]; // 对数组中的每个元素进行异或运算}return result; // 返回结果,即只出现一次的数字
}

交换两个变量:不使用临时变量交换两个变量的值。

// 函数定义:交换两个整数的值
void swap(int *x, int *y) {if (*x != *y) { // 检查两个指针指向的值是否不同,避免相同的内存地址操作,导致结果归零// 通过异或运算交换两个数的值*x ^= *y; // 将x的值与y的值进行异或,结果保存回x*y ^= *x; // 将y的值与上一步的结果(x的新值)进行异或,得到x的原始值,保存回y*x ^= *y; // 将x的值与y的新值(x的原始值)进行异或,得到y的原始值,保存回x}
}

例子说明过程:

假设我们有两个整数a = 5b = 3,我们想要交换它们的值。我们可以通过调用swap(&a, &b)来实现。

  1. 初始状态:a = 5b = 3
  2. 执行*x ^= *y;a = a ^ b = 5 ^ 3 = 6
  3. 执行*y ^= *x;b = b ^ a = 3 ^ 6 = 5(此时b已经变成了a的原始值)。
  4. 执行*x ^= *y;a = a ^ b = 6 ^ 5 = 3(此时a已经变成了b的原始值)。

最终结果:a = 3b = 5,成功交换了两个数的值。

注意:如果xy指向的是同一个内存地址,即*x*y是同一个数,那么上述交换操作会导致该数变为0,因为任何数与自身异或的结果都是0。因此,函数中加入了if (*x != *y)的检查来避免这种情况。

找出两个唯一未成对的数字:

在一个数组中,除了两个数字是唯一的,其他都成对出现。可以通过异或分组的方式找到这两个唯一的数字。

void findTwoUniqueNumbers(int* nums, int numsSize, int* num1, int* num2) {int xor = 0;// 第一次遍历:对数组中所有元素执行异或操作。// 相同的数字会相互抵消,最终结果是两个唯一数字的异或结果。for (int i = 0; i < numsSize; i++) {xor ^= nums[i];}// 找到异或结果中任意一个为1的位,我们这里选择最右边的一个。// 这一位能够帮助我们区分两个唯一的数字。int rightmostSetBit = xor & ~(xor - 1); *num1 = 0; // 初始化结果变量*num2 = 0; // 初始化结果变量// 第二次遍历:根据rightmostSetBit将数组分组,并分别异或。// 因为rightmostSetBit是两个唯一数字之间的不同位,所以它可以将这两个数字// 分到不同的组中,而成对出现的数字会被分到同一组并在异或中抵消。for (int i = 0; i < numsSize; i++) {if ((nums[i] & rightmostSetBit) != 0) {// 如果nums[i]在rightmostSetBit位上是1,说明它和其中一个唯一数字// 在该位上不同,因此将其与num1进行异或运算。*num1 ^= nums[i];} else {// 否则,说明它和另一个唯一数字在该位上不同,将其与num2进行异或运算。*num2 ^= nums[i];}}
}

数组中的两个元素求和:

虽然异或操作本身不直接用于求和,但在某些特定的位操作问题中,如求两个非负整数的和而不使用加号或其他算术运算符时,可以用异或来模拟加法操作中的“不进位求和”,同时用与操作和左移操作来模拟进位操作。

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

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

相关文章

基于二维CS-SCHT变换和扩频方法的彩色图像水印嵌入和提取算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................. % figure; % subplot(121);…

Visual Studio C++ 2019进行安装

Visual Studio C 2019进行下载安装 链接&#xff1a;https://my.visualstudio.com/Downloads?qvisual%20studio%202017&wt.mc_idomsftvscom~older-downloads

SwiGLU激活函数

SwiGLU激活函数已经成为LLM的标配了。它是GLU的变体&#xff0c;公式如下&#xff1a; SwiGLU ⁡ ( x , W , V , b , c , β ) Swish ⁡ β ( x W b ) ⊗ ( x V c ) \operatorname{SwiGLU}(x, W, V, b, c, \beta)\operatorname{Swish}_\beta(x Wb) \otimes(x Vc) SwiGLU(x,…

开源免费的发票识别OCR应用:Invoice

Invoice&#xff1a;轻松识别&#xff0c;发票电子化扫描烦恼消- 精选真开源&#xff0c;释放新价值。 概览 Invoice 是github社区上一个采用开源许可协议发布的增值税发票光学字符识别&#xff08;OCR&#xff09;解决方案项目。该项目不仅集成了预训练的高级模型&#xff0c…

Python | Leetcode Python题解之第78题子集

题目&#xff1a; 题解&#xff1a; class Solution:def subsets(self, nums: List[int]) -> List[List[int]]:self.res []self.backtrack([], 0, nums)return self.resdef backtrack(self, sol, index, nums):self.res.append(sol)for i in range(index, len(nums)):self…

Jenkins +git +web(vue) centos8.5 实战打包部署 运维系列二

1新建一个工程 #cat qy.sh #!/bin/bash cd /data/.jenkins/workspace/web rm -rf dist/ rm -rf qysupweb.tar.gz npm run build tar -czvf qysupweb.tar.gz dist/ #点击构建

基于控制工程的牛鞭效应simulink建模与仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 牛鞭效应”对供应链性能和绩效产生了严重的影响。基于控制理论建立了多级线性供应链的模型&#xff0c;分别利用噪声带宽和Matlab&#xff0f;Simulink对一个可扩…

平航杯复现

简单介绍及前期操作 esxi镜像挂载是一个新的创新点 就根据官方的wp进行挂载就可以了&#xff0c;后面差不多常规的服务器取证操作&#xff0c;然后服务器和计算机&#xff0c;u盘取证都有点联系&#xff0c;还是需要队友配合好一点 配置网段我的建议是把本机的配置改一下&am…

box-decoration-break 使用介绍

box-decoration-break属性的使用 一、定义 box-decoration-break是CSS片段模块&#xff08;CSS Fragmentation Module Level 3&#xff09;中的一个属性&#xff0c;主要用于指定背景&#xff08;background&#xff09;、内边距&#xff08;padding&#xff09;、边框&#…

低代码在物品领用领域数字化转型的案例分析

办公用品管理数字化不仅代表了企业管理模式的革新&#xff0c;更是提升运营效率和成本控制的关键举措。通过数字化手段&#xff0c;企业能够实现采购、库存、领用等流程的自动化和智能化管理&#xff0c;大幅减少人工操作&#xff0c;提高处理速度&#xff0c;确保数据的准确性…

ruoyi-nbcio 基于flowable规则的多重并发网关的任意跳转

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; h…

如何使用Python下载哔哩哔哩(Bilibili)视频字幕

在本文中&#xff0c;我将向大家展示如何使用Python下载哔哩哔哩&#xff08;Bilibili&#xff09;视频的字幕。通过这个方法&#xff0c;你可以轻松地获取你喜欢的视频的字幕文件&#xff0c;方便学习和交流。 准备工作 在开始之前&#xff0c;我们需要安装一些必要的库&…

熟悉Redis吗,那Redis的过期键删除策略是什么

对于Redis&#xff0c;我们业务开发一般都只关心Redis键值对的查询、修改操作&#xff0c;可能因为懒或者只想能用就行&#xff0c;呵呵。很少关心键值对存储在什么地方、键值对过期了会怎么样、Redis有没什么策略处理过期的键、Redis处理过期键又有什么作用&#xff1f;但这些…

固定资产管理系统参考论文(论文 + 源码)

【免费】固定资产管理系统.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89282536 固定资产管理系统 摘 要 随着计算机信息技术的发展以及对资产、设备的管理科学化、合理化的高要求&#xff0c;利用计算机实现设备及资产的信息化管理已经显得非常重要。 固…

LeetCode例题讲解:快乐数

编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。如果这个过程 结果为 1&#xff0c…

System Verilog通过CORDIC算法迭代16次求sin和cos值

求5~85度的sin和cos值 其它角度和Verilog实现代码类似&#xff0c;查表、移位和加法器 define DIE 16 //迭代次数 define PIE 3.1415926 define MUL 100_000_000 //同比放大 initial begin int die; int x[17]; int y[17]; int z[17…

Isaac Sim 3(学习笔记5.8)

Isaac Sim 利用深度学习获取mask掩码图 参考内容 Kubernetes官网 在 Linux 系统中安装并设置 kubectl | Kubernetes准备开始 kubectl 版本和集群版本之间的差异必须在一个小版本号内。 例如&#xff1a;v1.30 版本的客户端能与 v1.29、 v1.30 和 v1.31 版本的控制面通信。 用…

NodeMCU ESP8266 操作 SSD1306 OLED显示屏详解(图文并茂)

文章目录 1 模块介绍2 接线介绍3 安装SSD1306驱动库4 源码分析4.1 硬件兼容性4.2 可能存在的问题总结1 模块介绍 我们将在本教程中使用的OLED显示屏是SSD1306型号:单色0.96英寸显示屏,像素为12864,如下图所示。 OLED显示屏不需要背光,这在黑暗环境中会产生非常好的对比度。…

三轴加速度计LIS2DUX12开发(3)----计步器

三轴加速度计LIS2DUX12开发.3--轮询获取加速度数据 计步器硬件准备视频教学样品申请源码下载步数检测说明通信模式管脚定义IIC通信模式速率生成STM32CUBEMXIIC配置INT配置串口配置CS和SA0设置串口重定向参考程序初始换管脚获取ID复位操作BDU设置设置传感器的量程启用步数计和嵌…

矩阵:一个用于大型语言模型的贝氏学习模型

在本文中&#xff0c;作者介绍了一个贝氏学习模型来理解大型语言模型&#xff08;LLM&#xff09;的行为。他们探讨了基于预测下一个token的LLM优化指标&#xff0c;并开发了一个以此原理为基础的新颖模型。他们的方法涉及构建一个理想的生成文本模型&#xff0c;该模型由具有先…