【第0007页 · 数组】数组中重复的数据(如何实现数组的原地修改)

2024-09-08 09:12

本文主要是介绍【第0007页 · 数组】数组中重复的数据(如何实现数组的原地修改),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【前言】本文以及之后的一些题解都会陆续整理到目录中,若想了解全部题解整理,请看这里:

第0007页 · 数组中重复的数据

        今天,我们来看一个在实际工作中运用不多,但是对于一些算法题还是有必要的奇技淫巧——数组的原地修改。下面我们将通过两道题目来学习这种技巧。

【找到所有数组中消失的数】 给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

示例1示例2
输入描述:nums = [4, 3, 2, 7, 8, 2, 3,1]输入描述:nums = [1, 1]
输出描述:[5, 6]输出描述:[2]

【解题分析】这道题本来十分简单,但是如果加上一个要求:在不使用额外空间且时间复杂度为 O(n) 的情况下解决这个问题吗? 可以假定返回的数组不算在额外空间内。那么这道题就有些内容可以说了。

        这里我们先来讲解一下这种原地修改的想法:首先,由于 nums 的长度恰好为 n,而我们要查找的数字范围均在 [1, n] 中,那么我们不妨将位置 k 处的值当成数字 k + 1 是否出现的凭证。以上是 Hash 的思想。

        接下来,我们需要考虑如何才能使位置 k 处的值能够代表数字 k + 1 是否出现过。我们提供一种想法是如果 k + 1 出现过,需要将位置 k 处的值加上 n,因为本来数组中所有的数都小于 n,只能是由于出现过而导致大于 n。根据以上想法,我们就可以使位置 k 处的值能够代表数字 k + 1 是否出现过。

【源码展示】

class Solution {
public:vector<int> findDisappearedNumbers(vector<int>& nums) {int n = nums.size();for (int num : nums) {int x = (num - 1) % n;nums[x] += n;}vector<int> ret;for (int i = 0; i < n; i++) {if (nums[i] <= n) {ret.push_back(i + 1);}}return ret;}
};

         解决完上面这道题,我们再来看今天的第二题,中间也需要用到类似的思想。

【数组中重复的数据】给你一个长度为 n 的整数数组 nums ,其中 nums 的所有整数都在范围 [1, n] 内,且每个整数出现 一次 或 两次 。请你找出所有出现 两次 的整数,并以数组形式返回。

你必须设计并实现一个时间复杂度为 O(n) 且仅使用常量额外空间(不包括存储输出所需的空间)的算法解决此问题。

示例1示例2示例3
输入:nums = [4,3,2,7,8,2,3,1]输入:nums = [1,1,2]输入:nums = [1]
输出:[2.3]输出:[1]输出:[1]

【解题分析】这里和上面一题的要求几乎一致,思路也差不多,就留给读者自行思考了

【源码展示】

class Solution {
public:vector<int> findDuplicates(vector<int>& nums) {int size = nums.size();for (int i = 0; i< size; i++) {// Swap until appear in right poswhile (nums[i] != nums[nums[i] - 1]) {swap(nums[i], nums[nums[i] - 1]);}}vector<int> ans;for (int i = 0; i < size; i++) {if (nums[i] != (i+1)) {ans.emplace_back(nums[i]);}}return ans;}
};

这篇关于【第0007页 · 数组】数组中重复的数据(如何实现数组的原地修改)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1147701

相关文章

Android实现悬浮按钮功能

《Android实现悬浮按钮功能》在很多场景中,我们希望在应用或系统任意界面上都能看到一个小的“悬浮按钮”(FloatingButton),用来快速启动工具、展示未读信息或快捷操作,所以本文给大家介绍... 目录一、项目概述二、相关技术知识三、实现思路四、整合代码4.1 Java 代码(MainActivi

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

使用Python实现一个优雅的异步定时器

《使用Python实现一个优雅的异步定时器》在Python中实现定时器功能是一个常见需求,尤其是在需要周期性执行任务的场景下,本文给大家介绍了基于asyncio和threading模块,可扩展的异步定... 目录需求背景代码1. 单例事件循环的实现2. 事件循环的运行与关闭3. 定时器核心逻辑4. 启动与停

基于Python实现读取嵌套压缩包下文件的方法

《基于Python实现读取嵌套压缩包下文件的方法》工作中遇到的问题,需要用Python实现嵌套压缩包下文件读取,本文给大家介绍了详细的解决方法,并有相关的代码示例供大家参考,需要的朋友可以参考下... 目录思路完整代码代码优化思路打开外层zip压缩包并遍历文件:使用with zipfile.ZipFil

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

C#实现将Excel表格转换为图片(JPG/ PNG)

《C#实现将Excel表格转换为图片(JPG/PNG)》Excel表格可能会因为不同设备或字体缺失等问题,导致格式错乱或数据显示异常,转换为图片后,能确保数据的排版等保持一致,下面我们看看如何使用C... 目录通过C# 转换Excel工作表到图片通过C# 转换指定单元格区域到图片知识扩展C# 将 Excel

基于Java实现回调监听工具类

《基于Java实现回调监听工具类》这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录监听接口类 Listenable实际用法打印结果首先,会用到 函数式接口 Consumer, 通过这个可以解耦回调方法,下面先写一个

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Qt中QGroupBox控件的实现

《Qt中QGroupBox控件的实现》QGroupBox是Qt框架中一个非常有用的控件,它主要用于组织和管理一组相关的控件,本文主要介绍了Qt中QGroupBox控件的实现,具有一定的参考价值,感兴趣... 目录引言一、基本属性二、常用方法2.1 构造函数 2.2 设置标题2.3 设置复选框模式2.4 是否

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指