package java_jianzhioffer_algorithm;
/**
* 题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。
* 数组中某些数字是重复的,但不知道有几个数字是重复的。
* 请找出数组中任意一个重复的数字。
* eg:输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
* @author hexiaoli
*思考:
*1)建立一个计数数组(或者哈希表做),出现一次,对应标号加1
*2) 没有重复的情况,0-n-1范围内的数字,i应该出现在下标为i的位置
* 从头到尾扫描数组,比较第i个位置元素m,若相等则扫描下一个,
* 若不等比较m位置上的值是否和这个相等,若相等则找到。
*引申:不允许对数组排序
* 二分思想,将1-n按照m分成两部分,前面一半为0-m,后面一半为m+1-n
* 若前面一半的数字超过m+1,说明重复的数组在前面一半,否则在后面一半
*/
public class MinNumberInrotateArray {
public boolean duplicate1(int[] numbers,int length,int [] duplication) {
//检查数组内数是否合法
if(numbers == null || length ==0) {
return false;
}
for(int i = 0; i<length ;i++) {
if(numbers[i] < 0 || numbers[i] > length) {
return false;
}
}
//只需扫描一次原序列,就统计出所有元素出现的次数
int[] count = new int [length];
for(int i = 0; i<length ;i++) {
count[numbers[i]]+=1;
}
//再扫描一次数组,找到一个出现次数大于1的值即可
for(int i = 0; i < length; i++){
if(count[i] > 1){
duplication[0] = i;
System.out.println("duplication[0]:"+duplication[0]);
return true;
}
}
return false;
}
public boolean duplicate2(int[] numbers,int length,int [] duplication) {
//检查数组内数是否合法
if(numbers == null || length ==0) {
return false;
}
for(int i = 0; i<length ;i++) {
if(numbers[i] < 0 || numbers[i] > length) {
return false;
}
}
int temp = 0;
for(int i = 0; i < length ;i++) {
while(numbers[i]!=i){
if(numbers[i]==numbers[numbers[i]]) {
duplication[0]=numbers[i];
System.out.println("duplication[0]:"+duplication[0]);
return true;
}else {
temp = numbers[i];
numbers[i] = numbers[temp];
numbers[temp] = temp;
}
}
}
return false;
}
public boolean duplicate3(int[] numbers,int length,int [] duplication) {
//检查数组内数是否合法
if(numbers == null || length ==0) {
return false;
}
for(int i = 0 ; i < length ; i++) {
if(numbers[i] < 0 || numbers[i] > length) {
return false;
}
}
// 记录一下首尾
int start = 0;
int end = length-1;
while(end >= start) {
int mid = ((end-start+1)>>1) + start;
//统计前一半
int count = countRange(numbers,length,start,mid);
//首尾相等的话,则指向了单个元素
if(end == start) {
//如果这个元素统计值大于2,则是重复的值,并输出;否则跳出循环
if(count > 1) {
duplication[0] = start;
System.out.println("duplication[0]:"+duplication[0]);
return true;
}else {
break;
}
}
if(count > (mid -start + 1)) {
end = mid;
}else {
start = mid+1;
}
}
return false;
}
//统计数组中大于start小于end的元素个数
public int countRange(int[] numbers,int length,int start,int end ) {
int count = 0;
if(numbers == null || length == 0) {
return -1;
}
for(int i = 0; i < length;i++) {
if(numbers[i] >= start && numbers[i] <= end) {
++count;
}
}
return count;
}
public static void main(String[] args) {
int[] numbers = {2,3,1,0,2,5,3};
int length = numbers.length;
MinNumberInrotateArray mia = new MinNumberInrotateArray();
int[] duplication=new int [length];
mia.duplicate1(numbers, length, duplication);
mia.duplicate2(numbers, length, duplication);
mia.duplicate3(numbers, length, duplication);
}
}
剑指offer(50)数组中重复的数字
猜你喜欢
转载自blog.csdn.net/hxl0925/article/details/89343899
今日推荐
周排行