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

news2024/11/20 16:32:35

题目链接: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; // 初始化结果变量为0
    for (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.coloradmin.cn/o/1654990.html

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

相关文章

浙大×移动云,携手点亮AI新时代

近年来&#xff0c;中国移动依托强大的算网资源优势&#xff0c;围绕大模型训练、推理和应用三大场景&#xff0c;打造了一站式智算产品体系。该体系旨在为客户提供覆盖资源、平台、应用的AI全链路服务。目前&#xff0c;一站式智算产品体系已在浙江大学智算中心和许昌中原智算…

瓷器三维虚拟展示编辑平台为您量身定制高效实惠的展示方案

在竞争激烈的机械产品行业中&#xff0c;如何脱颖而出、展现产品魅力与企业实力?深圳vr公司华锐视点以其独特的三维动画设计制作服务&#xff0c;为您量身定制全方位的展示方案&#xff0c;让您的机械产品在市场中熠熠生辉。 全方位展示&#xff0c;细节尽收眼底 我们的三维展…

odoo17 音视频扩展

ODOO内置了音视频服务&#xff0c;同时也提供了与第三方平台Twilio的接口&#xff0c;用以实现音视频的扩展&#xff1a; Twilio是美国一家云通讯公司&#xff0c;算是云通讯领域的巨头企业&#xff0c;与同行业的公司以销售&营销进行投资来促进业务增长不同&#xff0c;T…

韩国站群服务器在全球网络架构中的重要作用?

韩国站群服务器在全球网络架构中的重要作用? 在全球互联网的蓬勃发展中&#xff0c;站群服务器作为网络架构的核心组成部分之一&#xff0c;扮演着至关重要的角色。韩国站群服务器以其卓越的技术实力、优越的地理位置、稳定的网络基础设施和强大的安全保障能力&#xff0c;成…

深度学习中的注意力机制二(Pytorch 16)

一 Bahdanau 注意力 通过设计一个 基于两个循环神经网络的编码器‐解码器架构&#xff0c;用于序列到序列学习。具体来说&#xff0c;循环神经网络编码器将长度可变的序列转换为固定形状的上下文变量&#xff0c;然后循环神经网络 解码器根据生成的词元和上下文变量按词元生成…

转转小程序数据处理

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872&#xff0c;x30184483x…

今天遇到一个GPT解决不了的问题

问题描述 你好&#xff0c;postman的一个post请求&#xff0c;编辑器里面放了一个很长的json数据&#xff0c;报Tokenization is skipped for long lines for performance reasons. This can be configured via editor.maxTokenizationLineLength.&#xff0c;但是同样的数据&a…

YOLOv9全网最新改进系列:YOLOv9完美融合标准化的注意力模块NAM,高效且轻量级的归一化注意力机制,助力目标检测再上新台阶!

YOLOv9全网最新改进系列&#xff1a;YOLOv9完美融合标准化的注意力模块NAM&#xff0c;高效且轻量级的归一化注意力机制&#xff0c;助力目标检测再上新台阶&#xff01;&#xff01;&#xff01; YOLOv9原文链接戳这里&#xff0c;原文全文翻译请关注B站Ai学术叫叫首er B站全…

基于模糊控制的AMT自动变速汽车换档智能控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于模糊控制的AMT自动变速汽车换档智能控制系统simulink建模与仿真。 2.系统仿真结果 输入的V&#xff0c;Ac&#xff0c;a 输出的档位&#xff1a; 3.核心程序与模型 版…

基于MPPT最大功率跟踪和SVPWM的光伏三相并网逆变器simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于MPPT最大功率跟踪和SVPWM的光伏三相并网逆变器simulink建模与仿真。包括PV模块&#xff0c;MPPT模块&#xff0c;SVPWM模块&#xff0c;电网模块等。 2.系统仿真结果 1不…

Pytorch常用的函数(九)torch.gather()用法

Pytorch常用的函数(九)torch.gather()用法 torch.gather() 就是在指定维度上收集value。 torch.gather() 的必填也是最常用的参数有三个&#xff0c;下面引用官方解释&#xff1a; input (Tensor) – the source tensordim (int) – the axis along which to indexindex (Lo…

Linux中gitlab-runner部署使用备忘

环境&#xff1a; 操作系统:&#xff1a;CentOS8 gitlab版本&#xff1a;13.11.4 查看gitlab-runner版本 可以从https://packages.gitlab.com/app/runner/gitlab-runner/search找到与安装的gitlab版本相近的gitlab-runner版本以及安装命令等信息&#xff0c;我找到与13.11.4相…

【离散数学】集合上二元关系性质判定的实现(c语言实现)

实验要求 关系矩阵的初始化和打印 我们将关系矩阵存入一个二维数组中&#xff0c;因为集合元素个数不会超过5个所以就用一个5行5列二维数组来表示。 在我们得到了集合元素个数之后我们就可以对数组进行0,1随机赋值 //初始关系矩阵 void init_matrix(int array[][5], int n) {…

【数据结构|C语言版】栈和队列

前言1. 栈1.1 栈的概念和性质1.2 顺序栈1.3 链栈1.4 共享栈 2. 队列2.1 队列的概念和性质2.2 循环队列2.3 链式队列2.4 双端队列 3. 例题精选3.1 有效的括号3.2 用队列实现栈2.4 用栈实现队列3.4 设计循环队列3.5 参考答案 结语 #include<GUIQU.h> int main { 上期回顾: …

centos8.5 安装 redis 7.2.4 详细步骤

1 下载Index of /releases/ (redis.io) 通过xftp等方式上传到服务器&#xff0c;安装依赖包 yum install gcc gcc-c make tcl -y [rootlocalhost software]# ll total 3308 -rw-r--r--. 1 root root 3386861 May 3 21:56 redis-7.2.4.tar.gz [rootlocalhost software]# ll…

SlowFast报错:ValueError: too many values to unpack (expected 4)

SlowFast报错&#xff1a;ValueError: too many values to unpack (expected 4) 报错细节 File "/home/user/yuanjinmin/SlowFast/tools/visualization.py", line 81, in run_visualizationfor inputs, labels, _, meta in tqdm.tqdm(vis_loader): ValueError: too …

软件测试之测试用例详细解读

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、通用测试用例八要素   1、用例编号&#xff1b;    2、测试项目&#xff1b;   3、测…

CSS---复合选择器和元素显示模式(三)

一、CSS的复合选择器 1.1 什么是复合选择器 在CSS中&#xff0c;可以根据选择器的类型把选择器分为基础选择器和复合选择器&#xff0c;复合选择器是建立在基础选择器之上&#xff0c;对基本选择器进行组合形成的。 复合选择器是由两个或多个基础选择器连写组成&#xff0c;它…

算法学习Day2——单调栈习题

第一题&#xff0c;合并球 题解&#xff1a;一开始写了一次暴力双循环&#xff0c;直接O(n^2)严重超时&#xff0c;后面于是又想到了O(n)时间复杂度的链表&#xff0c;但是还是卡在 最后一个数据会TLE&#xff0c;我也是高兴的拍起来安塞腰鼓和华氏护肤水&#xff0c;后面学长给…

信息系统项目管理师0094:项目管理过程组(6项目管理概论—6.4价值驱动的项目管理知识体系—6.4.3项目管理过程组)

点击查看专栏目录 文章目录 6.4.3项目管理过程组1.适应型项目中的过程组2.适应型项目中过程组之间的关系6.4.3项目管理过程组 项目管理过程组是为了达成项目的特定目标,对项目管理过程进行的逻辑上的分组。项目管理过程组不同于项目阶段:①项目管理过程组是为了管理项目,针对…