My code:
public class Solution {
public int findDuplicate(int[] nums) {
if (nums == null || nums.length == 0)
return -1;
int begin = 1;
int end = nums.length;
while (begin < end) {
int mid = begin + (end - begin) / 2;
int counter = 0;
for (int i = 0; i < nums.length; i++)
if (nums[i] <= mid)
counter++;
if (counter > mid)
end = mid;
else
begin = mid + 1;
}
return begin;
}
}
这道题目我没能想出来。感觉有点考智商。那个想法我的确没想出来。
首先贴一个博文。
http://bookshadow.com/weblog/2015/09/28/leetcode-find-duplicate-number/
然后这道题目有O(n) 的做法。但是感觉思路太复杂了。就忽略了。
然后思考了下他的第二种做法, O(n log n)
举个例子:
假设n = 9
那么,有10个位置放入1-9
肯定会有重复。
取中间值 1 + (10 - 1) / 2 = 5;
在1-9中, <= 5 的应该有5个,假设不重复。
但是如果1-5之间有数字重复了,那么,就应该大于5个了。
所以,遍历下整个数组,统计 <=5 的个数,如果大于5,那么就表示,
那个重复的数字,他的值v , 1 <= v <= 5
也就是
begin <= v <= mid
反之,则是:
mid + 1 <= v <= end
于是采用binary search 的思想,一步步往下缩小范围。最终,就能把v限定在一个确定值里面,此时,
begin = end
所以,最终可以找到这个值。
**
总结: 不在是binary search array, 而是 通过 binary search 来限定一个可能性取值的范围。最终达到目的。
**
Anyway, Good luck, Richardo!
My cdoe:
public class Solution {
public int findDuplicate(int[] nums) {
if (nums == null || nums.length == 0)
return -1;
int begin = 1;
int end = nums.length -1; // end = n
while (begin < end) {
int target = (begin + end) / 2;
int count = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] >= begin && nums[i] <= target)
count++;
}
if (count > target - begin + 1) {
end = target;
}
else {
begin = target + 1;
}
}
return begin;
}
}
寒假在家效率实在太低。这道题目再做也还是没有做出来。shit
思路还是听巧妙地。
Anyway, Good luck, Richardo!
My code:
public class Solution {
public int findDuplicate(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}
int i = 0;
while (i < nums.length) {
if (nums[nums[i] - 1] != nums[i]) {
int temp = nums[nums[i] - 1];
nums[nums[i] - 1] = nums[i];
nums[i] = temp;
}
else if (nums[i] - 1 == i) {
i++;
continue;
}
else {
return nums[i];
}
}
return -1;
}
}
这道题目的思想和
http://www.jianshu.com/p/fc874688359e
差不多。
然后看了下以前的做法,也是真的巧妙啊。感觉复杂度也是O(n)啊 ?
Anyway, Good luck, Richardo! -- 09/01/2016
最新的做法不太对。因为我修改了原数组。这是不允许的。
所以一开始的做法才是正确的。
Anyway, Good luck, Richardo! -- 09/11/2016