劍指Offer-題53(二)(Java版):0到n-1中缺失的數字
阿新 • • 發佈:2019-02-06
參考自:《劍指Offer——名企面試官精講典型程式設計題》
題目:0到n-1中缺失的數字
一個長度為n-1的遞增排序陣列中的所有數字都是唯一的,並且每個數字都在範圍0到n-1之內。在範圍0到n-1的n個數字中有且只有一個數字不在該陣列中,請找出這個數字。
主要思路:若陣列沒有缺失,則每個數字和它的下標都相等。然而,現在陣列有缺失,說明從缺失的那個數開始,後面的數字都比它的下標大1。因此找出第一個數值和下標不相等的數,那麼,它的下標就是缺失的那個數。
陣列可看成兩部分,前半段數值和下標相等,後半段數值和下標不相等,且陣列是有序的。所以,使用二分查詢,若中間數的值和下標相等,則在後半段繼續尋找;若中間數的值和下標不相等,且中間數的前一個元素的值等於它的下標相等,那麼這個中間數就是第一個值和下標不相等的數,它的下標就是缺失的那個數,否則繼續在前半段尋找。
關鍵點:二分查詢,數值和下標的關係
時間複雜度:O(logn)
public class MissingNumber
{
public static void main(String[] args)
{
System.out.println(findMissingNumber(new int[]{0, 1, 2, 3, 4})); //5
System.out.println(findMissingNumber(new int[]{1, 2, 3, 4})); //0
System.out.println(findMissingNumber(new int[]{0, 1, 2, 4, 5})); //3
}
private static int findMissingNumber(int[] data)
{
if (data == null || data.length <= 0) return -1;
int left = 0;
int right = data.length - 1;
//值和下標相等的數在陣列前半段
//值和下標不相等的數在陣列後半段
while (left <= right)
{
int middle = left + (right - left) / 2;
//值和下標不相等
if (data[middle] != middle)
{
//找到缺失的數
if (middle == 0 || data[middle - 1] == middle - 1)
{
return middle;
} else
{
right = middle - 1; //中間值和下標不相等,則需在前半段查詢
}
} else left = middle + 1; //中間值和下標相等,則需在後半段查詢
}
//陣列前面的數都和下標相等,說明缺失的是最大的那個數
if (left == data.length) return data.length;
return -1;
}
}