三种解法实现剑指 Offer 03. 数组中重复的数字
Posted 来老铁干了这碗代码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三种解法实现剑指 Offer 03. 数组中重复的数字相关的知识,希望对你有一定的参考价值。
立志用最少的代码做最高效的表达
题目链接——>传送门
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
限制:
2 <= n <= 100000
解法一:排序
解决这个问题一个简单办法就是先把输入的数组排序,从排序的数组中找出重复的数字是一件很容易的事情,只需从头到尾扫描即可。
时间复杂度为O(nlogn),空间复杂度O(1)
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(),nums.end());
for(int i = 1; i < n; i++){
if(nums[i-1] == nums[i])return nums[i];
}
return -1;
}
};
解法二:哈希表
构造一个长度为n的哈希表,遍历数组,每扫描到一个数字,都判断其是否在哈希表中存在,若不存在,则加入;若存在,则为重复数字。
时间复杂度为O(nlogn),空间复杂度O(n)
代码一:c++内置容器unordered_map实现(耗时较高)
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_map<int,int>um;
int k = 0;
for(auto i : nums) {
um[i]++;
if(um[i] > 1) {
k = i; break;
}
}
return k;
}
};
代码二:数组模拟哈希表(耗时低,因为数组效率高)
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int a[100005] = {0};
int k = 0;
for(auto i : nums) {
a[i]++;
if(a[i] > 1) {
k = i; break;
}
}
return k;
}
};
解法三:原地置换
现在让我们重排这个数组。从头到尾依次扫描这个数组中的每个数字。
当扫描到下标为i的数字时,首先比较这个数字(用m表示)是不是等于i。
如果是,则接着扫描下一个数字;如果不是,则再拿它和第m个数字进行比较。
如果它和第m个数字相等,就找到了一个重复的数字(该数字在下标为i和m的位置都出现了);如果它和第m个数字不相等,就把第i个数字和第m个数字交换,把m放到属于它的位置。
接下来再重复这个比较、交换的过程,直到我们发现一个重复的数字。
以数组{2,3,1,0,2,5,3}为例来分析找到重复数字的步骤。数组的第0个数字(从0开始计数,和数组的下标保持一致)是2,与它的下标不相等,于是把它和下标为2的数字1交换。交换之后的数组是{1,3,2,0,2,5,3}。
此时第О个数字是1,仍然与它的下标不相等,继续把它和下标为1的数字3交换,得到数组{3.1.2.0.2.5.3}。
接下来继续交换第0个数字3和第3个数字0,得到数组{0.1.2.3.2.5.3}。此时第О个数字的数值为0,接着扫描下一个数字。
在接下来的几个数字中,下标为1、2、3的3个数字分别为1、2、3,它们的下标和数值都分别相等,因此不需要执行任何操作。
接下来扫描到下标为4的数字2。由于它的数值与它的下标不相等,再比较它和下标为2的数字。
注意到此时数组中下标为2的数字也是2,也就是数字2在下标为2和下标为4的两个位置都出现了,因此找到一个重复的数字。
时间复杂度为O(n),空间复杂度O(1)
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int i = 0, len = nums.size();
while(i < len) {
if(nums[i] == i) {
i++;
continue;
}
if(nums[i] != nums[nums[i]]) {
swap(nums[i], nums[nums[i]]);
} else {
return nums[i];
}
}
return -1;
}
};
——朝着一个目标不断做精深练习,不断犯错,不断挑战自己的极限,这种努力给你带来的收获绝对超出你的想象
以上是关于三种解法实现剑指 Offer 03. 数组中重复的数字的主要内容,如果未能解决你的问题,请参考以下文章