题目:在非负数组(乱序)中找到最小可分配的id(从1开始编号),数据量1000000(就是找到从1开始最小的一个数:在数组中没有出现过的最小的数)数组中的数是【1,1000000】
方法1:暴力:从1开始依次探测每个自然数是否在数组中 O(n^2)
public class 最小可用ID {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr= {5,4,3,1,2,8,9};
int re = find1(arr);
System.out.println(re);//6
}
//方法1:暴力:从1开始依次探测每个自然数是否在数组中 O(n^2)
public static int find1(int[] arr){
int i = 1;
while(true) {
if(!appear(arr,i)) {
return i;
}
i++;
}
}
public static boolean appear(int[] arr,int i) {
for(int j =0;j<arr.length;j++) {
if(arr[j] == i) {
return true;
}
}
return false;
}
}
方法二:调用排序的方法,排好序过后一定都是按【1,2,3....】等等依次排下去的当出现第一个数没有连接的话可以通过数组下标发现
import java.util.Arrays;
public class 最小可用ID {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr= {5,4,8,1,3,2};
int re = find2(arr);
System.out.println(re);//6
}
//调用排序
public static int find2(int[] arr) {
Arrays.sort(arr);
int temp = 0;
for(int i = 0; i<arr.length;i++) {
if(i+1!=arr[i]) {
return i+1;
}
temp = i+2;
}
return temp;
}
}
方法三:创建辅助空间:要找到这个数组中未出现的最小的数(这个数必然是1----arr.length这两个数之间的一个数)所以我们只需要对原数组中小于等于arr.length的数在辅助空间进行标记就行(出现的标记为true,没有出现的标记为false),然后找到辅助空间的第一个false就可以了。所以我们可以发现这个算法的时间复杂度为O(n)。
注意:可以处理重复出现数
import java.util.Arrays;
public class 最小可用ID {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr= {5,4,8,1,3,2};
int re = find3(arr);
System.out.println(re);//6
}
//方法三:创建辅助空间
public static int find3(int[] arr) {
boolean[] help = new boolean[arr.length];//数组中的所有元素已经初始化了,默认为false
for(int i = 0;i<arr.length;i++) {
if(arr[i]<=arr.length) {//只对1---arr.length之间的数进行标记
help[arr[i]-1] = true;
}
}
int temp = 0;
for(int i = 0;i<arr.length;i++) {
if(!help[i]) {
return i+1;
}
temp = i+2;
}
return temp;
}
}
方法4:不通过辅助空间:通过找到该数组中间大小的数(就是排序过后这个数位于中间的那个数),我们可以通过让这个数与下标+1的大小进行比较,如果相等说明前面的数是紧密的(意思是从1,2,。。。接着一个一个的,没有缺少的),如果大于,说明前面有空缺(要找的数在前面即左侧);
注意:不能处理重复出现的数的问题
调用方法的代码:第k个元素-快排思想_羡云不羡君的博客-CSDN博客
//方法四
public static int find4(int[] arr,int l ,int r) {
if(l>r) {//递归的出口
return l+1;
}
int midIndex = l+((r-l)>>1);
int q = 第K小的数.SelectK(arr, l, r, midIndex-l+1);//实际在中间位置的值
int t= midIndex+1;//期望值
if(q==t) {//左侧紧密
return find4(arr,midIndex+1,r);
}else //左侧稀疏
return find4(arr,l,midIndex-1);
}