//找出唯一的duplicate number 不能修改nums 用O(1)space
//想到了swap 这里有个技巧 我们swap到对应的index 如果nums[index]被index这个数已经占了 就说明index这个数字有两个
//但是写完开始跑才发现不太对 因为swap了之后 index=i位置上并没有“排好” 而是index=nums[i]的排好了。所以这个时候i往后走是很不负责任的。
class Solution {
public int findDuplicate(int[] nums) {
for (int i = 0; i < nums.length; i++) {
//swap(nums, nums[i], nums[nums[i]]);
if (nums[i] == nums[nums[i]]) { //nums[i] 应该被放到 index == nums[index]的地方 如果已经被占了
return nums[i];
} else {
swap(nums, i, nums[i]);//被swap的应该是两个index
}
}
return -1;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
上面代码不对 为了改正 我们必须牺牲一点时间复杂度
改了改 写出下面这个 但是也不对 在数字多的时候TLE
//找出唯一的duplicate number 不能修改nums 用O(1)space
//想到了swap 这里有个技巧 我们swap到对应的index 如果nums[index]被index这个数已经占了 就说明index这个数字有两个
//但是写完开始跑才发现不太对 因为swap了之后 index=i位置上并没有“排好” 而是index=nums[i]的排好了。所以这个时候i往后走是很不负责任的。
//所以 我们用两个for 确保我们安排好i之后再移动
class Solution {
public int findDuplicate(int[] nums) {
for (int i = nums.length - 1; i > 0; i--) {
int count = 0;
int index = 0;;
for (int j = 0; j <= i; j++) {
//如果发现有一个相等的 就交换 如果发现有两个相等的 就有问题
if (nums[j] == i) {
count++;
index = j;
}
}
if (count == 1) {
swap(nums, index, i);
} else if (count == 2) {
return nums[index];//无所谓哪个
}
}
return nums[0];
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
还是他妈的不对 我认为是因为双层for的复杂度太高了
实际上这是用的binarySearch去解。
class Solution {
//解法1是抽屉原理
public int findDuplicate(int[] nums) {
int min = 0;
int max = nums.length - 1;
while(min <= max){
int mid = (max - min) / 2 + min;
int count = 0;
for(int i = 0; i<nums.length; i++){
if(nums[i] <= mid){
count++;
}
}
if(count > mid){ //如果小雨等于mid的数量>mid值,那就说明前半段里面肯定存在重复的
max = mid - 1;//因此缩小范围 降低下界
} else{
min = mid + 1;
}
}
return max + 1;
}
}
//为什么说 /如果小雨等于mid的数量>mid值,那就说明前半段里面肯定存在重复的 ?
//想象一下一个极端情况:【1,2,3,4,4, 4】
//min = 0 max = 5 mid = 2
//so count will be 2, and count <= mid, so the duplicate must exists in the right part