排序题目:丢失的数字

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
      • 进阶
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法三
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法四
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法五
    • 预备知识
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:丢失的数字

出处:268. 丢失的数字

难度

2 级

题目描述

要求

给定一个数组 nums \texttt{nums} nums,数组包含 n \texttt{n} n 个在范围 [0, n] \texttt{[0, n]} [0, n] 内的不同整数,返回该范围内唯一没有在数组中出现的数。

示例

示例 1:

输入: nums = [3,0,1] \texttt{nums = [3,0,1]} nums = [3,0,1]
输出: 2 \texttt{2} 2
解释: n = 3 \texttt{n = 3} n = 3,因为有 3 \texttt{3} 3 个数字,所以所有的数字都在范围 [0,3] \texttt{[0,3]} [0,3] 内。 2 \texttt{2} 2 是丢失的数字,因为它没有出现在 nums \texttt{nums} nums 中。

示例 2:

输入: nums = [0,1] \texttt{nums = [0,1]} nums = [0,1]
输出: 2 \texttt{2} 2
解释: n = 2 \texttt{n = 2} n = 2,因为有 2 \texttt{2} 2 个数字,所以所有的数字都在范围 [0,2] \texttt{[0,2]} [0,2] 内。 2 \texttt{2} 2 是丢失的数字,因为它没有出现在 nums \texttt{nums} nums 中。

示例 3:

输入: nums = [9,6,4,2,3,5,7,0,1] \texttt{nums = [9,6,4,2,3,5,7,0,1]} nums = [9,6,4,2,3,5,7,0,1]
输出: 8 \texttt{8} 8
解释: n = 9 \texttt{n = 9} n = 9,因为有 9 \texttt{9} 9 个数字,所以所有的数字都在范围 [0,9] \texttt{[0,9]} [0,9] 内。 8 \texttt{8} 8 是丢失的数字,因为它没有出现在 nums \texttt{nums} nums 中。

数据范围

  • n = nums.length \texttt{n} = \texttt{nums.length} n=nums.length
  • 1 ≤ n ≤ 10 4 \texttt{1} \le \texttt{n} \le \texttt{10}^\texttt{4} 1n104
  • 0 ≤ nums[i] ≤ n \texttt{0} \le \texttt{nums[i]} \le \texttt{n} 0nums[i]n
  • nums \texttt{nums} nums 中的所有数字各不相同

进阶

你能否实现 O(n) \texttt{O(n)} O(n) 时间复杂度和 O(1) \texttt{O(1)} O(1) 空间复杂度的解法?

解法一

思路和算法

首先将数组 nums \textit{nums} nums 升序排序。如果数组中没有数字丢失,则排序后的数组中,每个下标处的元素值都等于下标值。

假设丢失的数字是 x x x 0 ≤ x ≤ n 0 \le x \le n 0xn,则排序后的数组中,对于任意 0 ≤ i < x 0 \le i < x 0i<x 都有 nums [ i ] = i \textit{nums}[i] = i nums[i]=i。分别考虑 x < n x < n x<n x = n x = n x=n 的两种情况:

  • 如果 x < n x < n x<n,则 nums [ x ] ≠ x \textit{nums}[x] \ne x nums[x]=x x x x 是第一个元素值不等于下标值的下标;

  • 如果 x = n x = n x=n,则数组中的所有下标处的元素值都等于下标值。

因此只要遍历排序后的数组即可得到丢失的数字。遍历过程中,第一个元素值不等于下标值的下标即为丢失的数字。如果遍历结束之后没有发现元素值不等于下标值的下标,则范围 [ 0 , n − 1 ] [0, n - 1] [0,n1] 内的数字都不丢失,丢失的数字是 n n n

代码

class Solution {public int missingNumber(int[] nums) {Arrays.sort(nums);int n = nums.length;for (int i = 0; i < n; i++) {if (nums[i] != i) {return i;}}return n;}
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是数组 nums \textit{nums} nums 的长度。排序需要 O ( n log ⁡ n ) O(n \log n) O(nlogn) 的时间,遍历数组需要 O ( n ) O(n) O(n) 的时间,总时间复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn)

  • 空间复杂度: O ( log ⁡ n ) O(\log n) O(logn),其中 n n n 是数组 nums \textit{nums} nums 的长度。排序需要 O ( log ⁡ n ) O(\log n) O(logn) 的递归调用栈空间。

解法二

思路和算法

为了找到丢失的数字,可以使用哈希集合存储数组中的数字,然后寻找不在哈希集合中的数字。

由于所有的数字都在范围 [ 0 , n ] [0, n] [0,n] 内,因此依次遍历该范围的数字,判断每个数字是否在哈希集合中。具体做法是,首先遍历范围 [ 0 , n − 1 ] [0, n - 1] [0,n1] 内的每个数字,如果遇到不在哈希集合中的数字,则该数字是丢失的数字,返回该数字。如果范围 [ 0 , n − 1 ] [0, n - 1] [0,n1] 内的每个数字都在哈希集合中,则丢失的数字是 n n n,返回 n n n

代码

class Solution {public int missingNumber(int[] nums) {Set<Integer> set = new HashSet<Integer>();for (int num : nums) {set.add(num);}int n = nums.length;for (int i = 0; i < n; i++) {if (!set.contains(i)) {return i;}}return n;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要遍历数组 nums \textit{nums} nums 一次将数组中的所有数字加入哈希集合,然后需要遍历范围 [ 0 , n ] [0, n] [0,n] 内的每个数字寻找丢失的数字。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。哈希集合需要 O ( n ) O(n) O(n) 的空间。

解法三

思路和算法

解法二创建哈希集合需要 O ( n ) O(n) O(n) 的空间,如果可以原地哈希,则可以将空间复杂度降低到 O ( 1 ) O(1) O(1)

具体做法是,对于数组 nums \textit{nums} nums 的每个下标 i i i,如果 nums [ i ] < n \textit{nums}[i] < n nums[i]<n nums [ i ] ≠ i \textit{nums}[i] \ne i nums[i]=i,则将下标 nums [ i ] \textit{nums}[i] nums[i] 与下标 i i i 处的元素交换,交换之后 nums [ i ] \textit{nums}[i] nums[i] 的元素值等于下标值,重复该交换过程直到 nums [ i ] = n \textit{nums}[i] = n nums[i]=n nums [ i ] = i \textit{nums}[i] = i nums[i]=i,此时下标 i i i 处的元素无法继续交换。

当每个下标的交换操作都结束之后,遍历数组 nums \textit{nums} nums 寻找丢失的数字。遍历过程中,第一个元素值不等于下标值的下标即为丢失的数字。如果遍历结束之后没有发现元素值不等于下标值的下标,则范围 [ 0 , n − 1 ] [0, n - 1] [0,n1] 内的数字都不丢失,丢失的数字是 n n n

代码

class Solution {public int missingNumber(int[] nums) {int n = nums.length;for (int i = 0; i < n; i++) {while (nums[i] < n && nums[i] != i) {swap(nums, nums[i], i);}}for (int i = 0; i < n; i++) {if (nums[i] != i) {return i;}}return n;}public void swap(int[] nums, int index1, int index2) {int temp = nums[index1];nums[index1] = nums[index2];nums[index2] = temp;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要遍历数组 nums \textit{nums} nums 一次,每次会将一个元素交换到正确的下标位置,因此每个元素的访问次数是常数次,时间复杂度是 O ( n ) O(n) O(n)

  • 空间复杂度: O ( 1 ) O(1) O(1)

解法四

思路和算法

由于数组 nums \textit{nums} nums 中只有一个元素丢失,因此只要得到范围 [ 0 , n ] [0, n] [0,n] 内的所有整数之和以及数组 nums \textit{nums} nums 的所有元素之和,两者相减即可得到丢失的数字。

根据高斯公式可知,范围 [ 0 , n ] [0, n] [0,n] 内的所有整数之和是 n ( n + 1 ) 2 \dfrac{n(n + 1)}{2} 2n(n+1),因此可以在 O ( 1 ) O(1) O(1) 的时间内得到范围 [ 0 , n ] [0, n] [0,n] 内的所有整数之和。

代码

class Solution {public int missingNumber(int[] nums) {int sum = 0;for (int num : nums) {sum += num;}int n = nums.length;return n * (n + 1) / 2 - sum;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要遍历数组 nums \textit{nums} nums 一次计算数组元素之和。

  • 空间复杂度: O ( 1 ) O(1) O(1)

解法五

预备知识

该解法涉及到位运算中的按位异或运算。用 ⊕ \oplus 表示按位异或运算符,按位异或运算具有以下性质。

  • 交换律:对于任意整数 a a a b b b,有 a ⊕ b = b ⊕ a a \oplus b = b \oplus a ab=ba

  • 结合律:对于任意整数 a a a b b b c c c,有 ( a ⊕ b ) ⊕ c = a ⊕ ( b ⊕ c ) (a \oplus b) \oplus c = a \oplus (b \oplus c) (ab)c=a(bc)

  • 归零律:对于任意整数 a a a,有 a ⊕ a = 0 a \oplus a = 0 aa=0

  • 恒等律:对于任意整数 a a a,有 0 ⊕ a = a ⊕ 0 = a 0 \oplus a = a \oplus 0 = a 0a=a0=a

思路和算法

数组 nums \textit{nums} nums 中有 n n n 个整数,如果在这 n n n 个整数后面添加范围 [ 0 , n ] [0, n] [0,n] 内的每个整数各一个,则添加 n + 1 n + 1 n+1 个整数,共有 2 n + 1 2n + 1 2n+1 个整数。这 2 n + 1 2n + 1 2n+1 个整数中,未丢失的数字在前 n n n 个整数中以及在后 n + 1 n + 1 n+1 个整数中各出现一次,丢失的数字只在后 n + 1 n + 1 n+1 个整数中出现一次,因此每个未丢失的数字出现两次,丢失的数字出现一次。

利用按位异或运算的性质,对上述 2 n + 1 2n + 1 2n+1 个整数计算按位异或的结果。所有出现两次的数字经过按位异或运算之后的结果是 0 0 0,只有出现一次的数字在按位异或运算之后保留,因此上述 2 n + 1 2n + 1 2n+1 个整数的按位异或的结果即为丢失的数字。

代码

class Solution {public int missingNumber(int[] nums) {int xor = 0;for (int num : nums) {xor ^= num;}int n = nums.length;for (int i = 0; i <= n; i++) {xor ^= i;}return xor;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要遍历数组 nums \textit{nums} nums 一次以及遍历范围 [ 0 , n ] [0, n] [0,n] 内的所有整数计算按位异或的结果。

  • 空间复杂度: O ( 1 ) O(1) O(1)

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

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

相关文章

osg::Stats类用法及该类源码剖析

1. 概述 Stats是英文单词statistics的简写。顾名思义&#xff0c;就知道osg::Stats是osg中用来统计某些信息的类&#xff0c;如&#xff1a;帧率等&#xff0c;在osg中很多地方用到该类统计某些信息&#xff0c;如下代码是摘自osg的Viewer::eventTraversal()函数&#xff0c;该…

CentOS7.6安装RabbitMQ

前言&#xff1a;因为RabbitMQ是ERlang语言编写所以要先安装ERlang再安装RabbitMQ 安装ERlang 借鉴前辈原文地址&#xff1a;https://www.cnblogs.com/fengyumeng/p/11133924.html 第一步&#xff1a;安装依赖 yum -y install gcc glibc-devel make ncurses-devel open…

快速上手 Spring Boot:基础使用详解

快速上手 Spring Boot&#xff1a;基础使用详解 文章目录 快速上手 Spring Boot&#xff1a;基础使用详解1、什么是SpringBoot2、Springboot快速入门搭建3、SpringBoot起步依赖4、SpringBoot自动配置&#xff1a;以tomcat启动为例5、SpringBoot基础配置6、yaml7、多环境开发配置…

使用Ghostscript将PostScript(.ps)文件转换为PDF文件格式

如何使用Ghostscript将PostScript文件转换为PDF文件格式: /* Example of using GS DLL as a ps2pdf converter. */#if defined(_WIN32) && !defined(_Windows) # define _Windows #endif #ifdef _Windows /* add this source to a project with gsdll32.dll, or comp…

顶尖项目经理都在用的SOP

接受任务SOP 了解任务背景了解任务目标&#xff08;包含deadline&#xff09;拆解任务&#xff0c;确认负责人执行方案审批确认跟进执行并定期汇报验收结果&#xff0c;进行反馈相关文档存档&#xff0c;形成闭环 推进任务SOP - PDCA循环 制定计划 Plan。依据目标&#xff0c…

MacBook Pro 忘记root用户密码,重置密码步骤

一、以普通用户名登录系统&#xff0c;并打开terminal终端&#xff0c; 输入&#xff1a;sudo bash sudo bash Password:*****&#xff08;输入当前用户的密码&#xff09; 成功后进入bash-3.2#的命令模式 二、在bash-3.2#命令模式下 输入&#xff1a;sudo passwd root sud…

生信算法8 - HGVS转换与氨基酸字母表

HGVS 概念 HGVS 人类基因组变异协会(Human Genome Variation Society)提出的转录本编号&#xff0c;cDNA 参考序列(以前缀“c.”表示)、氨基酸参考序列(以前缀“p.”表示)。cDNA 中一种碱基被另一种碱基取代&#xff0c;以“>”进行表示&#xff0c;如&#xff1a;c.2186A&…

python数据分析——数据预处理

数据预处理 前言一、查看数据数据表的基本信息查看info&#xff08;&#xff09;示例 查看数据表的大小shape&#xff08;&#xff09;示例 数据格式的查看type()dtype&#xff08;&#xff09;dtypes&#xff08;&#xff09;示例一示例二 查看具体的数据分布describe()示例 二…

算法常见手写代码

1.NMS def py_cpu_nms(dets, thresh):"""Pure Python NMS baseline."""#x1、y1、x2、y2、以及score赋值x1 dets[:, 0]y1 dets[:, 1]x2 dets[:, 2]y2 dets[:, 3]scores dets[:, 4]#每一个检测框的面积areas (x2 - x1 1) * (y2 - y1 1)#按…

Windows环境如何ssh远程连接本地局域网内的Archcraft系统

文章目录 前言1. 本地SSH连接测试2. Archcraft安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接小结 5. 固定SSH公网地址6. SSH固定地址连接 前言 本文主要介绍如何在Archcraft系统中安装Cpolar内网穿透工具,并以实现Windows环境ssh远程连接本地局域网Archcraft系统来说明使用…

相位和展开相位

相位 (Phase) 相位是一个周期信号在一个周期内的位置&#xff0c;通常以角度&#xff08;度或弧度&#xff09;表示。在许多应用中&#xff0c;相位被限制在一个周期内。例如&#xff0c;相位通常被限定在 −180∘到 180∘ 或 0∘ 到 360∘ 之间。 示例 −90∘ 表示信号在周…

从基础到高级:视频直播美颜SDK的开发教学

本篇文章&#xff0c;小编将从基础到高级&#xff0c;详细讲解视频直播美颜SDK的开发过程&#xff0c;帮助开发者更好地掌握这一技术。 一、基础知识 什么是视频直播美颜SDK&#xff1f; 视频直播美颜SDK包含了一系列用于视频处理的功能模块&#xff0c;特别是美颜效果的实现…

C++支持哪些继承类型?

在C中&#xff0c;继承是一种面向对象编程&#xff08;OOP&#xff09;的特性&#xff0c;它允许一个类&#xff08;称为派生类或子类&#xff09;使用另一个类&#xff08;称为基类或父类&#xff09;的属性和方法。这种机制提高了代码的重用性&#xff0c;减少了代码的冗余&a…

Linux高并发服务器开发(一)GCC和Make

文章目录 1 工作流程2 静态库和动态库连接2.1 静态连接2.2 动态链接 3 静态库制作和使用4 动态库的制作和使用5 GDB 调试器6 Makefile 1 工作流程 第一步预处理&#xff0c;生成.i 第二部生成汇编文件.s 第三部生成目标代码.o 第四部生成可执行文件 2 静态库和动态库连接 2.1…

使用Mixamo极简绑骨,导入unity中使用

如果你只想专注于角色建模&#xff0c;对于动画设计没有过多精力&#xff1b;如果你想白嫖别人的角色动画&#xff0c;用到自己的模型上&#xff1b;那么&#xff0c;这个网站很适合你&#xff1a;https://www.mixamo.com/ 操作步骤&#xff1a; 首先将自己的模型上传到这个网…

精确控制激励功率,保障晶振正常工作

随着科技的发展&#xff0c;晶振在电子产品中的应用越来越广泛。作为电路中的重要组成部分&#xff0c;晶振的性能直接影响着整个电路的稳定性和可靠性。激励功率是影响晶振性能的关键因素之一&#xff0c;因此&#xff0c;对晶振激励功率的控制至关重要。 一、激励功率的含义…

海外短剧系统,开启你的国际视野

一、海外短剧系统是一个创新且富有吸引力的平台&#xff0c;它能够为用户提供来自世界各地的精彩短剧&#xff0c;从而开启用户的国际视野。 1、文化多样性&#xff1a;海外短剧系统汇集了来自不同国家和地区的短剧作品&#xff0c;这些作品反映了各自独特的文化背景和社会风貌…

在 Git 中创建新分支

在 Git 中创建新分支非常简单。你可以使用 git branch 命令来创建一个新的分支。以下是如何创建新分支的步骤&#xff1a; 首先&#xff0c;确保你当前在 Git 仓库的某个分支上。你可以使用 git status 来查看你当前所在的分支。 使用 git branch <branch-name> 命令来创…

主变变压器保护屏组成,功能介绍

主变变压器保护屏组成&#xff0c;功能介绍 在电力系统中&#xff0c;主变变压器是核心设备之一&#xff0c;对于保障电力系统的稳定运行起着至关重要的作用。为了确保主变变压器的正常运行&#xff0c;需要采用各种保护措施。其中&#xff0c;主变变压器保护屏是其中的重要组成…

Bootstrap 5 网格系统

Bootstrap 5 网格系统 Bootstrap 5 是目前最流行的前端框架之一,它提供了一套强大的网格系统,帮助开发者快速构建响应式布局。本文将详细介绍 Bootstrap 5 的网格系统,包括其工作原理、使用方法以及最佳实践。 什么是 Bootstrap 网格系统? Bootstrap 网格系统是一种基于…