问题描述
给定数组有n+1个元素,全都包含在[1,n]范围内,找出不止出现过一次的元素(它有可能重复多次)。
基础解法
设置一个二重循环,找到重复元素即将其返回。算法的时间复杂度为O(n²),是比较暴力的解法。
class Solution {
public:
int findDuplicate(vector<int>& nums) {
for (vector<int>::iterator it1 = nums.begin(); it1 != nums.end(); it1++) {
for (vector<int>::iterator it2 = it1+1; it2 != nums.end(); it2++) {
if (*it1 == *it2) return *it1;
}
}
}
};
升华探究
数组长度n和范围[1,n]已知,我们不妨设mid=(1+n)/2。遍历数组,若小于等于mid的元素的数目k小于mid,则将搜索范围缩小到[1,mid],反之则是[mid+1,n]。重复该步骤直至数组上下界相等,将其边界元素返回即可。使用二分查找,时间复杂度降低到o(logN),效率会有显著提升。
class Solution{
public:
int findDuplicate(vector<int>& nums) {
int n = nums.size()-1;
int low = 1;
int high = n;
int mid;
while(low < high){
mid = (low+high)/2;
int count = 0;
for(int num:nums){
if(num <= mid) count++;
}
if(count > mid) high = mid;
else low = mid+1;
}
return low;
}
};