一、剑指offer:03. 数组中重复的数字
03. 数组中重复的数字
一、题目描述
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3限制:
2 <= n <= 100000
二、解题思路
1、使用原地置换的法
数组元素的 索引和值是 一对多的关系。 因此,可遍历数组并通过交换操作,使元素的索引与 值一一对应(即 nums[i]=i )。这样就能通过索引映射对应的值,起到与字典等价的作用。
nums[i] | 2 | 3 | 1 | 0 | 2 | 5 | 3 |
---|---|---|---|---|---|---|---|
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
算法流程:
遍历数组 nums ,设索引初始值为 i=0 :
若nums[i]=i : 说明此数字已在对应索引位置,无需交换,因此跳过;
若nums[nums[i]]=nums[i] : 代表索引 nums[i] 处和索引 i 处的元素值都为 nums[i] ,即找到一组重复值,返回此值 nums[i] ;
否则: 交换索引为 i 和 nums[i] 的元素值,将此数字交换至对应索引位置。
若遍历完毕尚未找到,则返回 −1 。
①、判断vector容器是否为空;
②、初始值为 i=0开始遍历数组 nums :
③、判断nums[i]与i的关系,如果nums[i]=i ,则说明此数字已在对应索引位置,无需交换;如果不相等,则进行交换 temp = nums[nums[i]]; nums[nums[i]]=nums[i]; nums[i]=temp; 直到nums[i]=i; i+1进入下一次遍历;
④、如果nums[nums[i]]=nums[i] ,代表索引 nums[i] 处和索引 i 处的元素值都为 nums[i],即为我们要找的重复数字
复杂度分析:
时间复杂度 O(N): 遍历数组使用 O(N) ,每轮遍历的判断和交换操作使用 O(1);
空间复杂度 O(1) : 使用常数复杂度的额外空间。
具体程序实现:
1 |
|
输出:
1 | 0 1 1 0 2 5 3 |
程序具体的实现流程:
①、i = 0, nums[0] = 2 != 0;进入交换:temp = nums[nums[0]] = 1, nums[nums[0] = nums[0] = 2,nums[0] = 1;
则数组顺序变为:{1,3,2,0,2,5,3}
②、i = 0, nums[0] = 1 != 0; 进入交换:temp = nums[nums[0]] = 3, nums[nums[0] = nums[0] = 1,nums[0] = 3;
则数组顺序变为:{3,1,2,0,2,5,3}
③、i = 0, nums[0] = 3 != 0; 进入交换:temp = nums[nums[0]] = 0, nums[nums[0] = nums[0] = 3,nums[0] = 0;
则数组顺序变为:{0,1,2,3,2,5,3}
④、此时有nums[0] = 0;nums[1] = 1;nums[2] = 2;nums[3] = 3;
⑤、i = 4, nums[4] = 2 != 4; 进入if判断:nums[4] = nums[nums[4]]) = 2,则返回2