和力扣题目不一样,这里长度为n,要求数字范围是1~n-1,所以一定有重复数字
思路:找到最中间的值middleValue,比较小于它的数有多少个,如果个数小于等于这个值,这里有没有重复数字不知道,但大于这个值的数里一定有,所以再去大于这个数的范围里(middleValue~end)去找
package exercise01;
import java.util.HashSet;
import java.util.Set;
//不改变数组找出重复数字
//方法一:建立辅助数组,将原数组遍历,遍历出来的值(例如m)放到对应m位置,如果放置过了,说明m是重复的,这样空间复杂度o(n),时间复杂度也是o(n)
//方法二:二分查找,代码如下
public class ArrayDigitRepete3 {
public static void main(String[] args) {
int[] arr = new int[10];
//初始化
for (int i = 0;i < arr.length;i++){
arr[i] = (int)(Math.random()*(arr.length - 1)) + 1;//[1,length-1]数字范围,一定有重复数字
System.out.print(arr[i] + "\t");
}
System.out.println();
int repeatNumber = findRepeatNumber(arr);
System.out.println(repeatNumber);
}
public static int findRepeatNumber(int[] nums) {
if (nums.length == 0){
throw new RuntimeException("数组为空");
}
int start = 1;
int end = nums.length - 1;
while (start <= end){
int middleValue = (end + start)/2;
int count = 0;
for (int i = 0;i < nums.length;i++){
if (nums[i] <= middleValue && nums[i] >= start){
count++;
}
}
if (start == end){
if (count > 1){
return start;
}
}
if (count > (middleValue - start) + 1){
end = middleValue;
}else{
start = middleValue + 1;
}
}
return -1;
}
}