解题思路:
- 使用堆排序,构造小顶堆。时间复杂度O(nlogn),空间复杂度O(1)
- 使用HashMap,时间复杂度O(n),空间复杂度O(n)
- 原地哈希,时间复杂度O(n), 空间复杂度O(1)
具体实现:
/**
* 原地哈希算法 (哈希算法的改良版)
* 给定一个数组arr,数组长度为len,未出现的最小正整数一定不会超过len + 1,
* 即 [1, len] 这个区间的数都出现了,那么未出现的最小正整数就是len + 1,
* 否则未出现的最小正整数一定是[1, len]之间的某个数
*
* 我们应该使得arr[i] = i + 1,即i + 1这个数hash到i这个位置
* 如果arr[i] != i + 1,则i + 1这个数就没有出现
* return the min number
* @param arr int整型一维数组 the array
* @return int整型
*/
public int minNumberdisappered (int[] arr) {
// write code here
int len = arr.length;
if (len == 0) return 1;
// count: 数组中已经被占位的个数,即[1, len]区间已经出现的数的个数
int count = 0, i = 0;
while (count < len && i < len){
// i + 1已经哈希
if (arr[i] == i + 1){
count++;
i++;
continue;
}
//一个数>len或者<=0,它不会在arr数组的哈希范围里,无法占位
if(arr[i] > len || arr[i] <= 0) {
i++;
continue;
}
/*
使用交换的方式将数移到对应的位置,
交换后先不i++,因为交换后该位置上的数可能还在[1, len]这个区间里
*/
swap(arr, arr[i] - 1, i);
}
if (count == len)
return len + 1;
for (i = 0; i < len; i++){
if (arr[i] != i + 1)
return i + 1;
}
return 1;
}
/**
* 交换数字
* @param arr
* @param i
* @param j
*/
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}