Ⅰ.问题描述
Ⅱ.求解思路与推导
若可排序
比如给两个数组
数组1:[1,2,3,4,5,6,7,7] 重复数字是7
数组2:[1,1,2,3,4,5,6,7] 重复数字是1
数组长度
以数组1:[1,2,3,4,5,6,7,7]为例
将数值1-7分成两个区间
区间1{1,2,3,4},长度为4
区间2{5,6,7},长度为3
找出重复数
数组2:[1,1,2,3,4,5,6,7] 为例
数组数值落在区间1的数据为{1,1,2,3,4},个数超过区间长度
落在区间2的数值为{5,6,7},个数和区间长度相等
因此重复数据必然位于区间1上
再次将区间1二分
区间1{1,2}
区间2{3,4}
{1,1,2},个数超过区间长度
{3,4},个数和区间长度相等
再次将区间1二分
区间1{1}
区间2{2}
{1,1},个数超过区间长度
{2},个数和区间长度相等
所以1重复
本题不可改变数组顺序,但大体思路相同,给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。
(分治,抽屉原理) O(nlogn),将每个数的取值的区间[1, n]划分成[1, n/2]和[n/2+1, n]两个子区间,然后分别统计两个区间中数的个数。一定有一个区间个数大于取值范围。
Ⅲ.核心数据结构
#include<iostream>
#include<vector>
using namespace std;
int duplicateInArray(vector<int>& nums) {
int n = nums.size(); // n 表示数组的长度
int l = 1, r = n - 1;
while (l < r) {
int mid = (r - l) / 2 + l;//[1,mid][mid+1,r]
int sum = 0;
for (auto x : nums) {//用x遍历nums
if (l <= x && x <= mid)
sum++;
}
if (sum > mid - l + 1)
r = mid;
else
l = mid + 1;
}
return r;
}
int main() {
vector<int>v = {1,1,2,3,4,5,6,7,8};
cout << duplicateInArray(v) << endl;
return 0;
}