题目:
给定一个长度为 n+1 的数组nums
,数组中所有的数均在 1∼n的范围内,其中 n≥1。
请找出数组中任意一个重复的数,但不能修改输入的数组。
数据范围
1≤n≤1000
样例
给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。 返回 2 或 3。
解题思路
1.数组大小为n+1,取值范围是1~n,那么数组中至少有一个数字重复。
2.将数字范围二分,统计数组中数字在此二分范围内的的数量,如果大于二分长度,说明此二分范围内必有重复数字。反之则在另外一个二分区间。
3.依次类推,持续二分,缩小重复数字所在的区间范围,直到找到重复数字。
代码:
#include<iostream>
#include<vector>
using namespace std;
int Find(vector<int>arr)//二分法
{
int Left = 1;
int Right = arr.size() - 1;
while (Left < Right) {
int Mid = Left + Right >> 1;//将数字二分而不是将数组二分
int count = 0;//用于统计数字中元素大小在数字二分范围内的数目
for (auto x : arr)count += x >= Left && x <= Mid;//若数组元素大小在数字二分范围内则加一
if (count > Mid - Left + 1)
Right = Mid;
else
Left = Mid + 1;
}
return Left;
}
int main()
{
int n;
cin >> n;
vector<int>arr(n);
for (int i = 0; i < n; i++)
cin >> arr[i];
int m = Find(arr);
cout << "重复数字:" << m << endl;
}
算法原理:
分治,抽屉原理 O(nlogn)
这道题目主要应用了抽屉原理和分治的思想。
抽屉原理:n+1 个苹果放在 n 个抽屉里,那么至少有一个抽屉中会放两个苹果。