給定一個未排序的整數數組,找出其中沒有出現的最小的正整數。
示例 1:
輸入: [1,2,0]
輸出: 3
示例 2:
輸入: [3,4,-1,1]
輸出: 2
示例 3:
輸入: [7,8,9,11,12]
輸出: 1
你的算法的時間復雜度應為O(n),並且只能使用常數級別的空間O(1)。
這道題如果不要求時間復雜度為O(n)和空間O(1)的話,其實很簡單的,可以先對數組做一個排序,然后從小到大的找第一個缺失的正整數。但是排序的時間復雜度至少也是O(nlogn)。所以不能用排序的方法來進行查找。
對一個數組而言,其實最小的值排列就是[1…..length]的值,這個怎么理解呢。比如長度為4的數組,那么這個數組最小整數排列就是1,2,3,4。也就是長度為4的數組能容納的最小數就是1,2,3,4。那么對於任意一個長度為4的數組,缺失的最小正整數就一定在[1-length]之間的值。對於索引而言就是最小正整數一定存在於[1-index+1]的范圍。
既然最小的值和數組的索引有如此的關系,那么我們就可以借助索引的方法,將各個值放入到其對應的索引中去。比如i=4, num[i]=3, 那么我們就該把3和i=2的值進行互換。至於值超出數組長度或者負數,則不用去管。這樣能保證在數組長度范圍內的數都在起索引的位置上。變相起到了排序的功能。
用一個長度為5的數組來看下:
-1, 3, 5, 2, 7
Step1: i=0; num[i]=-1。不處理. i++
Step2: i=1; num[i]=3<5, 因此放入對應的索引位置,也就是3-1=2, 將num[1]和num[2]對換。數組變成-1,5,3,2,7.
Step3:i=2;num[i]=3 正好對應其索引位置,不處理,i++;
Step4:i=3 num[3]=2<5 放入對應的索引位置,也就是2-1=1, 將num[3]和num[1]對換。
數組變成-1,2,3,5,7
Step5:i=4 num[4]=7>5 不處理
最終的數組變成-1,2,3,5,7。 那么從數組開始判斷,看下num[i]是否是和i+1相等。如果不是,則缺失的最小正整數就是i+1。 上面的數組明顯就可以得出缺失的最小正整數就是0+1=1。
代碼如下:
int firstMissingPositive(int a[], int len)
{
int i,temp;
i = 0;
while(i<len)
{
if (a[i] < 0 || a[i] > len || a[a[i] - 1] == a[i])
{
i++;
}
else
{
temp = a[a[i] - 1];
a[a[i] - 1] = a[i];
a[i] = temp;
i++;
}
}
for (i = 0; i < len; i++)
{
if (a[i] != i + 1)
return i + 1;
}
return -1;
}
