You are given an infinite array A[] in which the first n cells contain integers in sorted order and the rest of the cells are filled with ∞. You are not given the value of n. Describe an algorithm that takes an integer x as input and finds a position in the array containing x, if such a position exists, in O(log n) time.
意思:
給定一個數組A[ ],包含無限個元素,前n個元素是排好序的,後面的值所有是無窮大。找到給定的目標x,若是x存在於前n個元素中,返回其索引。
要求時間複雜度是logn.
例子:
{1,2,3,4,7,9,11,18,20,31,36,65,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE}
若是找24,則找不到,返回-1。
若是找31,則找到,返回其索引9。數組
Solution:
排好序的數組,而且查找複雜度logN,能夠當即想到要用二分查找。rest
關鍵是這個無限大的數組,不知道右邊的邊界。因此要肯定右邊界,而且整體時間複雜度也不能超過logN。
logN 能夠想象爲樹的層數的概念,每層節點數是2^i,這樣子每次以該量級遞增,則複雜度是logN.
那麼使用位置1,2,4,8,16。。。依次判斷數組的該位置是不是MAX_VALUE,碰到就中止。這樣就能夠保證log級別的複雜度找到邊界。code
代碼實現:索引
public class FindKIndexFromInfinteArray { public static int solution(int[] array, int target){ int result = -1; // 處理邊界與特殊值 if(array == null || array.length == 0) return result; if(array[0] == Integer.MAX_VALUE) return result; else if(array[0] == target) return 1; int i = 1; while(array[i] != Integer.MAX_VALUE){// 遇到MAX就中止 if(array[i] == target) return i;// 在循環中若是碰到恰好等於目標值,就直接返回 i *= 2;//2,4,8,16,32。。。以指數級別上升 } // 此時i定位到一個右邊界,開始進行二分查找,從0到i result = binarySearch(array, target, 0, i); return result; } /** 二分查找*/ private static int binarySearch(int[] array, int target, int low, int high) { int left = low, right = high - 1; /* 若是這裏是 int right = n 的話,那麼下面有兩處地方須要修改,以保證一一對應: * 一、下面循環的條件則是while(left < right) * 二、循環內當array[middle]>value 的時候,right = mid */ while(left <= right){ int mid = left + ((right - left) >> 1); if(array[mid] > target) right = mid - 1; else if(array[mid] < target) left = mid + 1; else return mid; } return -1; } public static void main(String[] args) { int[] nums = {1,2,3,4,7,9,11,18,20,31,36,65,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE}; System.out.println(solution(nums, 31)); } }