287. Find the Duplicate Number 寻找重复元素

题目

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.

Example 1:

Input: [1,3,4,2,2]
Output: 2
Example 2:

Input: [3,1,3,4,2]
Output: 3
Note:

You must not modify the array (assume the array is read only).
You must use only constant, O ( 1 ) O(1) extra space.
Your runtime complexity should be less than O ( n 2 ) O(n^2) .
There is only one duplicate number in the array, but it could be repeated more than once.

题意

给定一个含有 n + 1 n+1 个元素的数组,里面的每个元素都属于 [ 1... n ] [1...n] ,里面有且只有一个元素会出现多次,把它找出来。
要求空间复杂度 O ( 1 ) O(1) ,时间复杂度小于 O ( n 2 ) O(n^2)

时间复杂度 O ( n l o g n ) O(nlogn) 的解法

在整个数组的最大值和最小值之间,二分寻找答案。
首先,扫描一遍数组,找到最大值l,最小值r。如果中途发现最大值或最小值出现了多次,则直接输出结果。

然后计算 mid = l + r 2 =\frac{l+r}{2} ,统计这个数组中比mid小的数字的个数less,以及mid自己出现的次数equal。

如果equal超过1,说明mid出现了多次,直接输出结果。

否则看 less有没有超过目标对象数字个数的一半,如果有说明重复元素在小于Mid,否则重复的元素大于mid。

class Solution {
public:
	int findDuplicate(vector<int>& nums) {
		int n = nums.size();
		int l = nums[0];
		int lc = 0;
		int r = nums[0];
		int lr = 0;
		for (int i = 1; i < n; i++)
		{
			if (nums[i] < l)
			{
				l = nums[i];
			}
			else if (nums[i] == l)
			{
				return l;
			}
			if (nums[i]>r)
			{
				r = nums[i];
			}
			else if (nums[i]==r)
			{
				return r;
			}
		}
		while (l<=r)
		{
			int mid = (l + r) / 2;
			int less = 0;
			int equal = 0;
			for (int i = 0; i < n; i++)
			{
				if (nums[i] < mid) less++;
				else if (nums[i] == mid) equal++;
				if (equal > 1) return mid;
			}
			if (less < mid)
			{
				l = mid + 1;
			}
			else
			{
				r = mid - 1;
			}
		}
		return l;
	}
};
发布了307 篇原创文章 · 获赞 268 · 访问量 56万+

猜你喜欢

转载自blog.csdn.net/jmh1996/article/details/102746757