1. 程式人生 > >劍指Offer(java+第八題,旋轉陣列的最小數字)

劍指Offer(java+第八題,旋轉陣列的最小數字)

 旋轉陣列的特點:
          1,旋轉之後的陣列可以分為兩個排序的子陣列,且前面的子陣列的元素都大於或等於後面子陣列的元素。
          2,最小或者最大元素位於兩個子陣列的分界
 解題思路:在排序陣列中,可以使用二分查詢法進行查詢
 利用左右兩個指標和中間指標元素大小關係判斷中間元素是位於前面的子陣列還是後面的子陣列,縮小查詢範圍
 需要考慮的特例:
         1,排序陣列本身仍是該陣列的一個旋轉
         2,如果陣列內有重複元素,那麼有可能出現左右兩指標元素與中間元素相同,無法判斷中間元素屬於前面子陣列還是後面子陣列,此時用順序查詢

/ * 如果把排序陣列前面的0個元素搬到最後面,即排序陣列本身,這仍然是陣列的一個旋轉。
 * 此時,陣列中的第一個數字就是最小的數字,可以直接返回,這就是 把indexMid初始化為index1的原因
 * 
 * 第一個指標最終將指向前面子陣列的最後一個元素,而第二個指標會指向後面子陣列的第一個元素。也就是他們最終會指向

 *兩個相鄰的元素,而第二個指標指向的更好是最小的元素。這就是迴圈結束的條件。

*/

程式碼:

public class Offer08 {
	
	public int minOfRotateArrays(int [] arrays) {
		if(arrays == null || arrays.length <= 0)
			//throw new RuntimeException("Invalid arrays");
			return 0;
		int index1 = 0;
		int index2 = arrays.length -1;
		int indexMid = index1;

		while(arrays[index1] >= arrays[index2]){
			if(index2 - index1 == 1){
				indexMid = index2;
				break;
			}
			
			indexMid = (index1 + index2)/2;
			//如果下標為index1、 index2和indexMin指向的三個數字相等,則只能順序查詢
			if(arrays[index1] == arrays[index2] && arrays[index1] == arrays[indexMid])
				return minInOrder(arrays, index1, index2);
			
			//旋轉陣列部分有序,可以使用二分查詢
			if(arrays[indexMid] >= arrays[index1])
				index1 = indexMid;
			else if(arrays[indexMid] <= arrays[index2])
				index2 = indexMid;
		}
		return arrays[indexMid];
	}
	
	public int minInOrder(int [] arrays, int index1, int index2){//順序查詢
		int result = arrays[index1];
		for(int i = index1+1; i<=index2;i++){
			if(result > arrays[i])
				result = arrays[i];
		}
		return result;
	}
	
	public static void main(String[] args) {
		Offer08 of8 = new Offer08();
		//測試用例
		//1,功能測試(輸入的陣列是升序排序陣列的一個旋轉,陣列中有重複的陣列或者沒有重複的數字)
		int [] array1 = {3,4,5,1,2};
		System.out.println("升序排序陣列的一個旋轉陣列,無重複數字:"+ of8.minOfRotateArrays(array1));
		
		int [] array2 = {3,4,5,1,1,2};
		int [] array3 = {1,0,1,1,1};//這個例子一般想不到,特別重要,這種情況二分法沒用,只能用順序查詢
		int [] array4 = {1,1,1,0,1};//這個例子一般想不到,特別重要,這種情況二分法沒用,只能用順序查詢
		System.out.println("升序排序陣列的一個旋轉陣列,有重複數字:"+ of8.minOfRotateArrays(array2));
		System.out.println("升序排序陣列的一個旋轉陣列,有重複數字:"+ of8.minOfRotateArrays(array3));
		System.out.println("升序排序陣列的一個旋轉陣列,有重複數字:"+ of8.minOfRotateArrays(array4));
		
		//2,邊界值測試,(輸入的陣列是一個升序排序的陣列、只包含一個數字的陣列)
		int [] array5 = {1,2,3,4,5};
		System.out.println("輸入陣列是一個升序排序陣列:"+ of8.minOfRotateArrays(array5));
		
		int [] array6 = {1};
		System.out.println("輸入陣列是隻包含一個數字的陣列:"+ of8.minOfRotateArrays(array6));
		
		//3,特殊輸入測試(輸入NULL指標)
		int [] array7 = null;
		System.out.println("輸入NULL指標:"+ of8.minOfRotateArrays(array7));
	}
}

執行結果: