剑指 Offer 03.:数组中重复的数字

剑指 Offer 03. 数组中重复的数字

找出数组中重复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3 

限制:

2 <= n <= 100000


思路分析:排序+查找

题目显而易见的一个解决方法是对该数组进行排序,然后在排序的数组中查找出重复元素就很容易了,至于排序的方法,为了熟悉一下快排,因此在这里我使用的是手写的快排。具体见下面的解法一。

C++代码:
class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
		int n = nums.size();
		//1.排序
		//也可以用库函数
		//sort(nums.begin(),nums.end());
		quickSort(nums,0,n-1);
		//2.查找
		for(int i=0;i<n;i++)
		{
			if(nums[i]==nums[i+1])
				{
					return nums[i];
				}
		}
		return -1;
    }
	
	//快排
	void quickSort(vector<int>&a,int left,int right)
	{
		//特判
		if(left>=right) return;
		int i = left-1;
		int j = right+1;
		int x = a[left+right>>1];
		while(i<j)
		{
			do i++;while(a[i]<x);
			do j--;while(a[j]>x);
			if(i<j)
			{
				swap(a[i],a[j]);
			}
		}
		//递归左边部分
		quickSort(a,left,j);
		//递归右边部分
		quickSort(a,j+1,right);
	}
};
复杂度:

时间:排序一个长度为n的数组需要 O(nlogn) 的时间。

空间:常数空间 O(1)


思路分析:(优化)哈希表

提到 重复二字,必然少不了哈希表。具体的,遍历整个数组,每次扫描数组中每一个值,可以判断其有没有在哈希表中,如果在,直接返回,否则,只需要更新一下哈希表状态即可。

C++代码:
class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        int n = nums.size();
		//开一个哈希表
        unordered_map<int,bool> mp;
		//遍历nums数组
        for(int i:nums)
        {
			//如果该值已存在,直接返回
            if(mp[i])
            {
                return i;
            }
			//更新一下哈希表的状态
            mp[i] = true;
        }
        return -1;
    }
};
复杂度:

时间:由于哈希表每次判断只需要O(1)的时间,长度为n的数组,因此复杂度为O(n)。

空间:毫无疑问,这种解法使得在时间上得到了优化,同时却是以牺牲O(n)的哈希表空间换取的,所以空间复杂度为O(n)


思路分析:(再优化)原地交换

原地交换??

在具体的题目中,有的解题方法是需要我们对题目已经其数据进行观察,找到规律进而得到一条捷径,这里不妨以提供的用例:[2, 3, 1, 0, 2, 5, 3]配合图解来加以论述该方法的可行性。

数组中的重复数字

很容易观察到,如果对没有重复数字的数组进行排序,那么排序之后的数字i将会出现在下标为i的位置。

复现一下这个重排的大致过程:

扫一遍数组,到下标为i时,首先判断一下该处的值(假如为v)是不是等于i

如果答案是肯定的,那么接着往下扫描下一个数。

如果不是,再拿它和第v个数字进行比较,如果此时它(这里指的是i)和v相等,说明找到了一个重复数字。

如果它和第v个数字不相等,就将把第i个数和第v个数进行交换,也就是把v放到原本属于它的位置。

重复以上比较、交换的过程,直到程序结束。

有点懵??再来亿遍,用例模拟。

还是上面的官方给的测试用例:[2, 3, 1, 0, 2, 5, 3]


第一步:i=0,判断:nums[0]==2!=0交换:swap(nums[0],nums[nums[0]])即是交换(2,1)的位置。

结果:[1, 3, 2, 0, 2, 5, 3]满足条件【nums[i]不等于ii不变,继续扫描。


第二步:i=0,判断:nums[0]==1!=0交换:swap(nums[0],nums[nums[0]])即是交换(1,3)的位置。

结果:[3, 1, 2, 0, 2, 5, 3]满足条件【nums[i]不等于ii不变,继续扫描。


第三步:i=0,判断:nums[0]==3!=0交换:swap(nums[0],nums[nums[0]])即是交换(3,0)的位置。

结果:[0, 1, 2, 3, 2, 5, 3]满足条件【nums[i]不等于ii不变,继续扫描。


第四步:i=0,判断:nums[0]==0满足条件【nums[i]==i】此时[0, 1, 2, 3, 2, 5, 3]``````i++继续下一轮比较。


第五步:i=1,判断:nums[1]==1满足条件【nums[i]==i】此时[0, 1, 2, 3, 2, 5, 3]``````i++继续下一轮比较。


第六步:i=2,判断:nums[2]==2满足条件【nums[i]==i】此时[0, 1, 2, 3, 2, 5, 3]``````i++继续下一轮比较。


第七步:i=3,判断:nums[3]==3满足条件【nums[i]==i】此时[0, 1, 2, 3, 2, 5, 3]``````i++继续下一轮比较。


第八步:i=4,判断:nums[4]==2!=4交换:swap(nums[4],nums[nums[4]])即是交换(2,2)的位置。

注意,这里我们发现此时交换的数字都是2,不过前者的下标为i=4,而后者下标i=2,就是说,此时我们已经找到了数组中的一个重复值,因此进行返回即可,该用例答案为2,程序结束。

C++代码:
class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
		int n = nums.size();
		if(n<2) return -1;
		for(int i=0;i<n;i++)
		{
			if(nums[i]<0) return -1;
		}
		for(int i=0;i<n;i++)
		{
			while(nums[i]!=i)
			{
				if(nums[i]==nums[nums[i]])
				{
					return nums[i];
				}
				swap(nums[i],nums[nums[i]]);
			}
		}
		return -1;
    }
};
复杂度:

时间:O(n)。

空间:O(1)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux下的进程管理:创建、终止、切换与等待

文章目录 一、引言二、进程创建1、进程创建的概念与场景2、进程创建的方式a、fork() 系统调用b、fork() 后的执行流程 3、进程创建的过程a、进程创建过程b、子进程创建过程 4、父子进程关系与属性继承 三、进程终止1、进程终止的原因2、进程的错误码和退出码a、错误码b、退出码…

Golang基础5-指针、结构体、方法、接口

指针 和c/c类似&#xff0c;但是go语言中指针不能进行偏移和运算&#xff0c;安全指针 &&#xff08;取地址) *(根据地址取值) nil(空指针&#xff09; make和new之前对比&#xff1a;make用于初始化slice&#xff0c;map&#xff0c;channel这样的引用类型 而new用于类…

热知识:更多团队采用3个及以上内部开发者平台

01 介绍 根据 Perforce Puppet 的一份新报告中&#xff0c;平台工程的采用已经在一些企业内看到了成效&#xff0c;78% 的受访者表示他们的组织拥有专门的平台团队至少三年了。 然而&#xff0c;这并不意味着这些组织只使用同一套工具。四分之三的调查参与者表示&#xff0c;他…

如何使用SOLIDWORKS添加装饰螺纹线规格

在我们的设计过程中&#xff0c;有很多的时候螺纹规格在机械设计手册上没有&#xff0c;而我们的SOLIDWORKS软件里面录制的都是符合标准的的螺纹&#xff0c;至于其他的特种或者超出的规格需要我们设计人员去手工添加&#xff0c;以下介绍我们装饰螺纹线新规格的添加方法&#…

关于PMO卓越中心职能建设的实践与思考︱PMO大会

全国PMO专业人士年度盛会 浪潮电子信息产业股份有限公司PMO时军先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“让组织持续卓越——关于PMO卓越中心职能建设的实践与思考”。大会将于5月25-26日在北京举办&#xff0c;敬请关注&#xff01; …

菜单访问url/接口url为什么要带时间戳

一&#xff0c; 问题 1&#xff0c;菜单url中如果不加时间戳&#xff0c;会导致什么问题。我们现在做一个东西&#xff0c;需要获取菜单的访问地址&#xff0c;我们要拼这个地址 2&#xff0c;查询接口中&#xff0c;时间戳&#xff0c;如果不加&#xff0c;具体导致什么问题 二…

Vue集成three.js,加载glb、gltf类型的3d模型

安装基本依赖 // 注意OrbitControls要加{}&#xff0c;注意路径是jsm import { OrbitControls } from ‘three/examples/jsm/controls/OrbitControls.js’; // import { dat } from ‘three/examples/jsm/controls/dat.gui.js’; // dat gui这个插件&#xff0c;是另外自己下载…

杰理使用USB声卡模式时关闭MIC

杰理在使用PC模式的时候&#xff0c;想只保留扬声器&#xff0c;但不要打开MIC功能&#xff0c;可以配置USB_DEVICE_CLASS_CONFIG中把MIC_CLASS去掉&#xff0c;然后重新编译就可以了。

Kimi 高效使用技巧,80%的人都不知道

关注我, AI 学习之旅上&#xff0c;我与您一同成长&#xff01; 一、引言 Kimi 作为国产之光&#xff0c;在过去的一个多月里成为国内大模型的香饽饽。据数据分析&#xff0c;Kimi 网页、APP、小程序等各端的日活已经突破 300 万&#xff0c;超过文心一言、通义千问、智谱清言…

单链表实现通讯录

不过多赘述了 顺序表的增删查改-CSDN博客https://blog.csdn.net/bkmoo/article/details/137566495?spm1001.2014.3001.5502 使用顺序表实现通讯录-CSDN博客https://blog.csdn.net/bkmoo/article/details/137676561?spm1001.2014.3001.5502这里没有使用文件操作只是简单的使…

6.MMD ray渲染 材质的添加及打光方法

材质 前置准备 先准备好模型和场景 将ray控制器拖入进去 添加完默认的材质以后的效果 打开插入材质页面 打开MaterialMap栏 将流萤的模型展开 自发光 现在给领带添加一个自发光效果 在自发光Emissive里&#xff0c;打开x1&#xff0c;选择albedo&#xff0c;白光 现在…

使用微软Phi-3-mini模型快速创建生成式AI应用

微软Phi-3大语言模型是微软研究院推出的新一代系列先进的小语言模型。Phi-3系列包括phi-3-mini、phi-3-small和phi-3-medium三个不同规模的版本。这些模型在保持较小的参数规模的同时&#xff0c;通过精心设计的训练数据集和优化的算法&#xff0c;实现了与大型模型相媲美的语言…

【CVPR2023】Re:InterHand:一个用于3D交互手部姿态估计的重光照数据集

这篇论文的标题是《A Dataset of Relighted 3D Interacting Hands》&#xff0c;作者是Gyeongsik Moon, Shunsuke Saito, Weipeng Xu, Rohan Joshi, Julia Buffalini, Harley Bellan, Nicholas Rosen, Jesse Richardson, Mallorie Mize, Philippe de Bree, Tomas Simon, Bo Pen…

玩转PyCharm

玩转PyCharm PyCharm是由JetBrains公司开发的提供给Python专业的开发者的一个集成开发环境&#xff0c;它最大的优点是能够大大提升Python开发者的工作效率&#xff0c;为开发者集成了很多用起来非常顺手的功能&#xff0c;包括代码调试、高亮语法、代码跳转、智能提示、自动补…

MyBatis 核心配置讲解(上)

大家好&#xff0c;我是王有志&#xff0c;一个分享硬核 Java 技术的互金摸鱼侠。 前两篇的文章中我们分别介绍了 MyBatis 和 MyBaits 的应用组成&#xff0c;到这里基础篇的内容就结束了。 从今天开始&#xff0c;我们正式进入 MyBatis 学习的第二阶段&#xff1a;MyBatis 的…

【QT学习】9.绘图,三种贴图,贴图的转换,不规则贴图(透明泡泡),简单绘图工具制作

一。绘图的解释 Qt 中提供了强大的 2D 绘图系统&#xff0c;可以使用相同的 API 在屏幕和绘图设备上进行绘制&#xff0c;它主要基于QPainter、QPaintDevice 和 QPaintEngine 这三个类。 QPainter 用于执行绘图操作&#xff0c;其提供的 API 在 GUI 或 QImage、QOpenGLPaintDev…

maya blendshape

目录 shape编辑器 maya创建blendshape python 脚本 添加形变动画 查看顶点个数 shape编辑器 打开方式&#xff1a; 窗口-动画编辑器-形变编辑器 maya创建blendshape python 脚本 import maya.cmds as cmds# 创建基础网格 - 球体 baseMesh cmds.polySphere(name"bas…

Postman 工具发送请求的技巧与实践

在开发和测试 API 时&#xff0c;发送 JSON 格式的请求是一个常见需求。 在 Postman 中构建和发送 JSON 请求 创建一个新的请求 首先&#xff0c;在 Postman 启动界面上找到并点击 “New” 按钮&#xff0c;选择 “HTTP Request” 来开始新建一个请求。这一步骤允许你定义请…

Unity射击游戏开发教程:(7)Powerup的使用

确定 PowerUp 效果应持续多长时间 我在游戏中放置的第一个道具是三重射击。当玩家收集三重射击能量时,他们可以一次发射 3 束激光,而正常情况下只能发射 1 束激光。在实施道具时,您需要考虑它们的功能以及它将如何影响游戏玩法。至于三连射&

Linux-缓冲区(简单理解)

1. 缓冲区是什么 缓冲区就是一段内存空间。 2. 为什么要有缓冲区 IO写入有两种&#xff1a; 写透模式&#xff08;WT&#xff09; 成本高&#xff0c;效率低写回模式&#xff08;WB&#xff09; 成本低&#xff0c;效率高 写透模式&#xff1a;每次的文件写入都要立即刷新…