1.长度为n的数组,元素大小为0-n-1,有些数字重复,找出任意一个重复数字。例如{2, 3, 1,0, 2, 5, 3} 对应输出2或3.
由于数字长度为n,数字大小为0到n-1,可以将数字i放置在数组中i位置,若数组中i位置上数字已经是i,则说明i数字重复了,否则则进行交换,将数字i放置在数组中i位置。
public static int findNum(int[] arr){
//遍历一遍将arr[i]放在索引为arr[i]位置上,当相等时说明数字重复,不相等则进行交换。
for(int i=0; i<arr.length; i++){
if(arr[i]==arr[arr[i]]){
return arr[i];
}else{
int m = arr[arr[i]];
arr[arr[i]] = arr[i];
arr[i] = m;
}
}
return -1;
}
2.不修改数组找出重复的数字,长度为n+1,数字范围在1-n之间,找出数组中重复的任意数字,不能修改数组。
1-n范围内数字有n+1个,说明某个数字重复了。取1-n的中间值m,分为1--m和m+1--n,统计数组中在1--m中元素个数,若大于m,则说明该数字在1--m中,否则在m+1--n中。类似于二分查找,终止条件是,lo==hi并且在这个区间里面的数字个数大于1,说明找到了重复值。
public static int findNum2(int[] arr){
int lo = 1;
int hi = arr.length-1;
while(lo <= hi){
int mid = (lo + hi) >> 1;
int leftNum = count(arr, lo, mid);
System.out.println("lo = " + lo + " mid = " + mid + " left num = " + leftNum);
if(lo == hi){
if(leftNum > 1) return lo;
else break;
}
if(leftNum > mid-lo+1)
hi = mid;
else
lo = mid + 1;
}
return -1;
}
public static int count(int[] arr, int lo, int hi){
int num = 0;
for(int i=0; i<arr.length; i++){
if(arr[i]>=lo && arr[i]<=hi)
num++;
}
return num;
}
3.二维数组的查找
二维数组从左到右递增 从上到下递增 查找是否存在某数。
以右上顶点为基准,若小于目标数,则下移,若大于目标数,则上移。
若数组无序,可以先排个序考虑一下,若数组有序,可以考虑二分法等查找方式
public static boolean findNum3(int[][] arr, int num){
int m = arr.length;
int n = arr[0].length;
while(m>=0 && n>=0){
if(arr[m][n]==num) return true;
else if(arr[m][n]>num) n--;
else m--;
}
return false;
}