最小可用ID:在非负数组(乱序)中找到最小的可分配的id(从1开始编号),数据量1000000
上面的数组的最小可用ID为1
这个数组的最小可用ID就为16
方法一:暴力解法------时间复杂度高O(n^2)
package smallid;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
public class smallid {
static class Util{
static int indexOf(int[] arr,int i) { //声明方法
return i;
}
}
//暴力解法O(n^2),从1开始依次探测每一个自然数是否在数组中
static int find1(int[] arr){
int i=1; //i从1开始
while(true) {
if(Util.indexOf(arr,i) == -1){ //找到没有的那个数返回
return i;
}
i++; //若不是,继续循环
}
}
}
方法二:快速排序,让数组变得有序后找出缺少的数------时间复杂度O(nlogn)
package smallid;
public class Smallidk {
static class Array{
static void sort(int[] arr) { //声明方法
return ;
}
int find2(int[] arr){
Array.sort(arr); //对数组进行排序
int i=0; //数组下标从0开始 ,i为数组下标
while(i<arr.length) {
if(i+1!=arr[i]) { //当数组下标和对应的数不匹配时
return i+1; //返回对应缺少的数
}
i++; //否则,继续循环
}
return i+1;
}
}
}
方法三:利用辅助数组进行扫描-------时间复杂度O(n)
辅助空间的数组下标表示该下标元素出现的次数
伪代码
helper=[A.length]
for(i:0.....A.length-1)
helper[A[i]-1=1; //下标转为数字
}
for(i:0......A.length-1 //扫描辅助空间
if(helper[i]==0) //若help的下标没有系数为1
return i+1;
}
return A.length+1;
代码
package smallid;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
import sun.applet.Main;
public class Smallid2 {
public static int find3(int[] arr) {
int n=arr.length; //定义数组长度
int[] helper=new int [n+1]; //定义辅助空间
for(int i=0;i<n;i++) { //构造辅助数组
helper[arr[i]]=1;
}
for(int i=1;i<=n;i++) { //扫描辅助数组
if(helper[i]==0) { //如果辅助空间数组下标出现次数为0
return i; //返回该元素
}
}
return n+1; //若数组长度范围内度存在,则返回n+1
}
public static void main(String[] args) {
int[] arr= {1,2,3,4,5,8,9,10,11,12};
long now=System.currentTimeMillis();
Object find2;
Smallidk find2=new Smallidk();
System.out.println(find2(arr));
Util.duration(now);
now=System.currentTimeMillis();
System.out.println(find3(arr));
Util.duration(now);
}
}
方法四:区间分割法
假设一个长度为100的数组
分为以下三种情况;
1.中间值恰好为50时,表明数组左半区间数字元素紧凑,没有要找的缺少元素
2.中间值为大于50的值,表明数组左半区间有漏掉的元素
package smallid;
public class Smallidfenqu {
public static int find4(int[] arr,int l,int r) { //定义数组,左指针,右指针
if(l>r)
return l+1;
int midIndx=l+((r-l)>>1); //中间下标,用右指针减去左指针加1
int q=selectk(arr,l,r,midIndex-l+1); //实际中间位置的值
int t=midIndex+1; //t为要求的期望值
if(q==t) { //左侧紧密
return find4(arr,midIndex+1,r); //在右半区间查找
}
else { //左侧稀疏
return find4(arr,l,midIndex-1); //在左半区间查找
}
}
public static void main(String[] args) {
int[] arr= {1,2,3,4,5,8,9,10,11,10000};
arr=new int[1000*1000];
}
}