AcWing 13.找出数组中重复的数字(循环交换)

二十一、CANdelaStudio深入-SPRMIB的配置 本专栏将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希望能对大家有所帮助,与大家共同成长,早日成为一名车载诊断、通信全栈工程师。 本文介绍CANdelaStudio的肯定响应抑制位配置,欢迎各位朋友订阅、评论,可以提出宝贵意见,以持续输出更好的作品,同时会根据评论、私信不定期更新文章内容,以及专栏目录。订阅该专栏的朋友可私信小编免费答疑解惑(^U^)ノ~YO CANdelaStudio-从入门到深入目录 文章目录CANdelaStu 阅读详情

1.方法1

简单来说就是开辟一个空间为n的向量用来做数字出现次数的统计。由于题目只要求返回任意一个重复的数字,因此只需遍历统计向量找到首个记录出现次数大于1的数字即可。

具体代码如下:

class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int n = nums.size();
        vector<int> v(n, 0);
        //检验越界元素并统计出现次数
        for(auto &e: nums){
            if(e < 0 || e >= n) return -1;
            v[e]++;
        }
        //遍历统计结果,若有满足条件的则返回
        for(int i = 0; i  <n; i++){
            if(v[i] > 1) return i;
        }
        //未发现则说明所有元素均不重复
        return -1;
    }
};

2.方法2

本方法参考题解。相比于上一个方法而言,此方法仍为线性的时间复杂度,不过空间复杂度却为常数。具体思路是:首先判断是否存在越界的元素,有则直接返回-1。没有则采用“循环交换”的方式来确定是否存在重复元素。

2.1“循环交换”原理

在理解循环交换之前,先思考这样一个问题。


Q2.1.1

我们假设所有的元素均满足以下条件:

1.全部都在规定的范围内且互不相同;

2.在数组中的次序是完全混乱的。

题目要求元素范围是从0到n-1的,恰好数组的下标也是从0到n-1的。因此,我们可以考虑将数组的下标与元素一一对应(下标0的位置存放数据0,下标1的位置存放数据1……以此类推)。那么对于一个元素次序完全混乱的数组,我们要怎样才能在O(1)的空间复杂度内让每个元素都能存放到自己对应的位置呢?


答案就是“交换”。首先我们按顺序遍历数组,如果当前位置的元素x就是本该对应此位置的元素则移到下一个位置。如果不是那么就将元素x与x本该对应的位置的元素进行交换,不断重复此交换操作,直到对应x原来所处位置的元素归位。如此进行就可以令所有的元素都能存放到对应的位置上。下面举个例子。


eg2.1.1

假设数组中元素次序为[0, 4, 1, 2, 3],那么整个处理过程如下:

1.[0, 4, 1, 2, 3] -> [0, 4, 1, 2, 3],因为0号位存放元素就是0,故数组不变;

2.[0, 4, 1, 2, 3] -> [0, 3, 1, 2, 4] -> [0, 2, 1, 3, 4] -> [0, 1, 2, 3, 4];

3.[0, 1, 2, 3, 4] -> [0, 1, 2, 3, 4];

4.[0, 1, 2, 3, 4] -> [0, 1, 2, 3, 4];

5.[0, 1, 2, 3, 4] -> [0, 1, 2, 3, 4];


而且,还可以证明:只要数组中的元素满足全部都在规定范围内且全部互异的条件。那么以上算法就一定可以将所有元素放置到其对应的位置上。

如果用代码来实现的话,那就是如下所示的样子:

for(int i = 0; i < n; i++){
    while(i != nums[i]) swap(nums[i], nums[nums[i]]);
}

while循环的含义是:当当前位置与其存放的元素不匹配时,便不断对此位置的元素进行交换操作。

那么假如我们破坏了互异的条件,再按照以上算法处理的话会怎样呢?再来看个例子。


eg2.1.2

假设数组中元素次序为[0, 4, 1, 2, 2],那么整个处理过程如下:

1.[0, 4, 1, 2, 2] -> [0, 4, 1, 2, 2];

2.[0, 4, 1, 2, 2] -> [0, 2, 1, 2, 4] -> [0, 1, 2, 2, 4];

3.[0, 1, 2, 2, 4] -> [0, 1, 2, 2, 4];

4.[0, 1, 2, 2, 4] -> [0, 1, 2, 2, 4] -> [0, 1, 2, 2, 4] ->……进入死循环!


从上面的例子可以看到,出于3号位的元素2不属于3号位,那么按照算法它应当与自己本属于的2号位的元素进行交换。然而2号位的元素已经是2了,即使交换过来了仍然不满足条件。于是两个2之间就不断地进行交换,从而让程序陷入了死循环。由此可以看出:如果数组中的元素满足全部都在规定范围。则“数组中存在重复的元素”与“以上算法在某一步会陷入死循环”互为充要条件。而这个结论正是循环交换找出重复元素的关键!

对于原来的问题而言,只要能检测是否发生交换死循环就可以判定数组中是否存在重复元素,而且导致发生死循环的元素也正是要找的重复的元素。

因此,我们需要对上面的for循环代码进行一些修改(确切来说是for里面的while循环)来满足我们的要求。我们的要求是:若没有死循环则正常进行交换操作,否则立即退出循环。于是,代码修改如下:

for(int i = 0; i < n; i++){
    while(i != nums[i] && nums[nums[i]] != nums[i]) swap(nums[i], nums[nums[i]]);
}

代码的修改其实就是添加了一段逻辑判断。逻辑与的前一部分仍是原来的含义,后一部分的意思是只有当当前位置元素与同其交换的元素不同时应进行交换。此时,如果退出了while循环则说明发生了两种情况:当前位置的元素已经归位或者是当前位置元素与同其交换的元素相同。

接下来要做的就是对这两种情况进行判断,如果发生的是第一种情况,则将遍历指针移到下一个位置(即contiune语句)。如果是第二种情况,则将当前位置的元素返回即可。将两个判断逻辑合并后就得到了如下的for循环结构体:

for(int i = 0; i < n; i++){
    while(i != nums[i] && nums[nums[i]] != nums[i]) swap(nums[i], nums[nums[i]]);
    if(i != nums[i] && nums[nums[i]] == nums[i]) return nums[i];
}

这样,结合我们的问题Q2.1.1和以上的分析,就可以轻而易举地理解“循环交换”的原理了。从而得到了解决问题的代码。

2.2实现

具体代码如下:

class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int n = nums.size();
        for (auto x : nums) //检查是否存在范围以外的元素
            if (x < 0 || x >= n)
                return -1;
        for (int i = 0; i < n; i ++ ) {
            while (nums[i] != i && nums[nums[i]] != nums[i])
                swap(nums[i], nums[nums[i]]);
            if (nums[i] != i && nums[nums[i]] == nums[i])
                return nums[i];
        }
        return -1; //for循环过程中未出现返回说明所有元素均互异
    }
};

2.3其他问题

如果大家有仔细将我的代码与题解的代码进行比对,会发现题解的while语句的逻辑判断语句中并没有我的while语句中的前一个逻辑。实际上从本题的解法上来说while语句中是否判断了当前位置元素是否归位并不影响程序的正确性。大家可以用上面的例子来对比两处语句的不同。

另外就是将while后面的if语句中的逻辑判断改写成一下形式:

if (nums[i] < i) return nums[i];

仍然不影响程序的正确性。大家可以思考一下这是为什么?

基于SVD矩阵分解的用户购物篮预测分析实战 阅读详情

相关推荐

利用图层自动识别算法实现CAD到Revit BIM模型的高效转换 - VS2022与AutoCAD2024开发环境配置指南

本文详细介绍了如何配置VS2022与AutoCAD2024开发环境,并利用图层自动识别算法实现CAD图纸到Revit BIM模型的高效自动化转换。通过解析CAD图层的规律性,该算法能智能识别并分类墙、门、窗等构件,提取几何信息并驱动Revit自动创建三维模型,从而将传统繁琐的人工“翻模”工作转化为高效、准确的自动化流程,大幅提升BIM模型创建效率。

Apple的专栏 1126

剑指offer:找出数组中重复的数字

用大白话,案例,图帮助你理解 剑指offer第一题:找出数组中重复的数字

xiaopeng683的博客 290

STM32F030F4P6 ADC多通道定时器触发DMA搬运

主函数中等待转换完成的标志位,然后打印出来。ADC回调函数中将数值赋值给变量。配置定时器1s读一次。

qq_24426625的博客 1356

[数组][简单]189.旋转数组

tags: 简单 完成 数组 flag: green style: summer date: ‘2019-6-25’ 189.旋转数组 一、题目 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。 示例 1: 输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右旋转 1 步: [7,1,2,3,4,5,6] 向...

GJXAIOU 的 优快云 博客 998

IMU卡尔曼滤波方法详细介绍

本文介绍了基于IMU和卡尔曼滤波的状态估计方法。系统采用9维状态向量(位置、速度、加速度计零偏),通过牛顿运动学建立状态方程,并利用外部位置观测进行校正。详细推导了状态转移矩阵和控制输入矩阵的形式,阐述了预测和更新的计算步骤。同时说明了过程噪声Q和观测噪声R的设置原则,其中Q反映模型不确定性,R取决于传感器精度。该方法可有效融合IMU测量与外部观测数据,实现位置、速度和偏置的联合估计。

haing2019的博客 757

3D坐标系转换实战:如何用Python快速实现旋转矩阵与平移向量的组合变换

本文详细介绍了如何使用Python和NumPy实现3D坐标系转换中的旋转矩阵与平移向量的组合变换。通过齐次坐标和变换矩阵的数学原理,结合代码示例,帮助开发者高效处理机器人路径规划和计算机视觉中的空间变换问题,并解决实际应用中的常见错误。

pluto的博客 959

算法学习——找出数组中重复的数字

本题采用了两种方式进行解答,欢迎各位大神指正。

weixin_62607846的博客 540

Dify使用教程(创建应用)

Dify的安装部署我已经写过了,简单的模型配置我也在前面进行了讲解,今天我们主要来讲讲如何使用Dify。

wal1314520的博客 1万+

oracle如何找出重复的列名_面试官:如何迅速找出数组中重复的数字?

推荐阅读:一只Tom猫:消息队列面试,你能顶得住面试官这波10大连环炮的攻势吗?​zhuanlan.zhihu.com一只Tom猫:三次阿里二面挂,Java+并发+JVM+网络+数据库+算法,我还能说啥?​zhuanlan.zhihu.com题目给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重...

weixin_39517797的博客 818

基于51单片机的贪吃蛇游戏设计

本科时候做的一个课程作业,自己打一个很简易的电路,比较有意思且易上手,故将之记录下来。(全套的仿真及代码,演示视频,课程报告以及PPT展示上传在优快云下载区) 一. 实验目的 (1) 通过对C51语言的理解,编写程序实现对贪吃蛇的有效控制; (2) 通过对51单片机硬件的学习,学会运用面包板,独立按键、点阵屏等,完成对完整电路的搭建过程; (3) 通过对Proteus仿真软件的学习,实现基于STC89C52单片机的8*8点阵贪吃蛇的硬件电路仿真。 二. 实验介绍 贪吃蛇是一款经典小游戏,其游戏的规则是:玩

山山の十三先生 2万+

Unreal5从入门到精通之Landscape地形系统

虚幻引擎 5 (UE5) 能够利用其强大的地形编辑工具套件创建大规模的地形世界。使用地形工具可以创建身临其境的户外地形,这些地形经过优化,可在多种不同设备上保持可播放的帧速率。

TxNet 4143

找出数组中重复的数字

剑指offer面试题三,提出了找出数组中重复的数字的两种解决方法,分别是移动数组和不移动数组。

weixin_41090596的博客 2437

基于MATLAB的数字滤波器之低通滤波器

本文首先介绍了数字低通滤波器的概念和原理,其次论述了低通滤波器的技术指标和设计步骤,最后给出了数字低通滤波器应用于信号去噪的MATLAB代码。

总结论文中的算法并给出论文的复现代码 3万+

AcWing 13 找出数组中重复的数字

题目描述: 给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1的范围内。 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。 注意:如果某些数字不在 0∼n−1的范围内,或数组中不包含重复数字,则返回 -1; 样例 给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。 返回 2 或 ...

昂昂累世士的博客 317

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

AcWing 13. 找出数组中重复的数字

题目描述 给定一个长度为n的整数数组nums,数组中所有的数字都在0∼n−1的范围内。 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。 请找出数组中任意一个重复的数字。 注意:如果某些数字不在0∼n−1的范围内,或数组中不包含重复数字,则返回 -1; 样例 给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。 返回 2...

yj_coder的博客 326

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【算法题】Acwing 13.14找出数组中重复数字

—考虑最坏的情况,就是n个数字,没有重复的,且i为0的时候,就去一直重复情况2,直到后面的n-1个数字都到了正确的位置,之后就一路i++,结束了!,数字范围是1~n,将其分成[1 , n/2 ]和[ n/2 + 1 ,n ]两个区间,分别统计这两个数字区间内数字的数量,肯定有一个区间内的数字个数比数字区间(end-start+1)更大;需要注意的是,最后的数字区间一定是只有一个数,这个数字就是答案,此时be = end,退出循环,故返回be和end都ok,但是不可以返回mid!

massive_jiang的博客 390

AcWing 13. 找出数组中重复的数字

找出数组中重复的数字题解

Lok877043018的博客 204

AcWing13+14: 找出数组中重复的数字(Java实现)

题目描述: 思路: 刚开始想的是建立一个统计数组,对原数组中的数字计数,若统计数组中有>1出现,则输出起index,即原数组中重复的数字。 但是这样空间复杂度上来了。大佬的解题方式:若没有重复的数字,则肯定是一个数字一个坑儿。可通过遍历数组,若i位置和其放的数nums[i]不相等,则将nums[i]放入其应该在的位置[nums[i]],再将nums[nums[i]]交换到[i]。交换过后如果nums[i] != i,则说明nums[i]并不应该在i位置,说明不是一个萝卜一个坑儿了,nums[

qq_40180352的博客 475

【剑指offer】 acwing 13. 找出数组中重复的数字

剑指offer 原题链接 给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1 的范围内。 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。 请找出数组中任意一个重复的数字。 注意:如果某些数字不在 0∼n−1 的范围内,或数组中不包含重复数字,则返回 -1; 数据范围 0≤n≤1000 样例 给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。 返回 2 或 3。 题解 我第一想到的是hashset hashmap之类的 不过这样的

qq_41810415的博客 164

ACWING13. 找出数组中重复的数字(剑指offer,置换法,下标法,思维)

给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1 的范围内。 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。 请找出数组中任意一个重复的数字。 注意:如果某些数字不在 0∼n−1 的范围内,或数组中不包含重复数字,则返回 -1; 样例 给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。 返回 2 或 3。 class S...

tomjobs的博客 570

剑指offer第一周(acwing打卡)

剑指offer13. 找出数组中重复的数字第一次写法:第二次写法:(推荐) 13. 找出数组中重复的数字 给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1 的范围内。 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。 请找出数组中任意一个重复的数字。 注意:如果某些数字不在 0∼n−1 的范围内,或数组中不包含重复数字,则返回 -1; 样例 给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。 返回 2 或 3。 返回 2 或 3。

骑着乌云看雪 409

剑指offer

目录AcWing 13. 找出数组中重复的数字AcWing 14. 不修改数组找出重复的数字AcWing 15. 二维数组中的查找 AcWing 13. 找出数组中重复的数字 class Solution { public: int duplicateInArray(vector<int>& nums) { int n = nums.size(); for (auto x : nums) //首先遍历数组,如果存在某个数不在0到n-

HENRYyangtuo的博客 320

【蓝桥杯PythonB组备赛】【Acwing周赛】第90场分析理解

A首字母大写;B 找数字;C 构造字符串 记录学习过程~python备赛蓝桥杯的可以看过来哦

weixin_60897770的博客 622

《剑指Offer》第1-11题

AcWing 13. 找出数组中重复的数字 给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1 的范围内。 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。 请找出数组中任意一个重复的数字。 注意:如果某些数字不在 0∼n−1 的范围内,或数组中不包含重复数字,则返回 -1; 样例 给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。 返回 2 或 3。 from collections import defaultdict class

pxlsdz的博客 569

Acwing 第一次周赛(1)

更多学习和讨论,欢迎加入我们!有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。这里有2000+小伙伴,让你的学习不寂寞~·

feifei99_8820的博客 821

AcWing解题目录(C++)

# 试题名称 思想方法 难度 试题来源 1 A+B 简单 AcWing 2 01背包问题 简单 3 完全背包问题 简单 4 多重背包问题I 简单 5 多重背包问题II 中等 6 多重背包问题...

Zee_Chao的博客 900
上一篇: AcWing 1.A+B
下一篇: AcWing 14. 不修改数组找出重复的数字(分治法)
Zee_Chao
博客等级 码龄11年 168粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值