1. 程式人生 > >leetcode解題之153&154. Find Minimum in Rotated Sorted Array版(在旋轉的陣列中查詢最小數字)

leetcode解題之153&154. Find Minimum in Rotated Sorted Array版(在旋轉的陣列中查詢最小數字)

153.Find Minimum in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

You may assume no duplicate exists in the array.

給定一個數組,陣列可能被旋轉了,但是在旋轉之前是遞增有序的,找出該陣列的的最小值。(陣列沒有重複值

複雜度等價於一個二分查詢,是O(logn),空間上只有四個變數維護二分和結果,所以是O(1)。

採用二分查詢的方法進行查詢。陣列的第一個元素要大於最後一個元素,因為陣列是遞增的,如果不小於則第一個元素就是最小的元素。如果不小於,初始化high=0,high=len-1,則取中間數mid,如果中間數大於high指向的元素,則說明小數存在後半段,則將high指向mid,否則將high指向mid,繼續進行尋找。

只需要判斷是否為遞增序列或者是否只有一個元素特殊情況即可,新增一句,if (nums[low] <= nums[high]) return nums[low];繼續二分查詢。等號判斷只有一個元素情況,小於判斷遞增序列。注意:如果

中間元素小於最左邊元素,則右部分為有序陣列。說明此時中間元素已經在最小值右側,不然不會小於最左側元素

154. Find Minimum in Rotated Sorted Array II

Follow up for "Find Minimum in Rotated Sorted Array":
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

The array may contain duplicates.

給定一個數組,陣列可能被旋轉了,但是在旋轉之前是遞增有序的,找出該陣列的的最小值。(陣列有重複值

兩道題解法一樣,有重複值只要判斷 low high mid三者指向的元素是否相等,相等就退化為O(N)複雜度。

	public int search(int[] nums, int target) {
		if (nums == null || nums.length < target)
			return 0;
		int low = 0;
		int res = 0;
		int high = nums.length - 1;
		if (nums[low] <= nums[high])
			res = Arrays.binarySearch(nums, target);
		else {
			int m = findMin(nums);
			System.out.println(m);
			res = Arrays.binarySearch(nums, 0, m, target);
			if (res < 0)
				res = Arrays.binarySearch(nums, m, high + 1, target);
		}
		if (res < 0)
			return -1;
		else
			return res;

	}
	
	public int findMin(int[] nums) {
		// ask interviewer which value should return:
		// Integer.MIN_VALUE or throw a Exception.
		if (nums == null || nums.length == 0)
			return -1;
		int low = 0;
		int mid = 0;
		int high = nums.length - 1;
		while (nums[low] >= nums[high]) {
			// 表示找到
			if (high - low == 1) {
				mid = high;
				break;
			}
			mid = (low + high) / 2;
			// 如果三個數字相等需要遍歷整個數字查詢最小值
			if (nums[mid] == nums[low] 
					&& nums[mid] == nums[high])
				return MinOrder(nums, low, high);
			// 處於遞增子序列中,最小值在右側
			if (nums[mid] >= nums[low])
				low = mid;
			else
				// 處於遞減子序列中,最小值在左側
				high = mid;
		}
		return nums[mid];
	}

	// 遍歷整個陣列求最小值
	private int MinOrder(int[] nums, int low, int high) {
		int min = nums[low];
		for (int i = low + 1; i <= high; i++)
			min = Math.min(min, nums[i]);
		return min;
	}
網上參考:http://www.programcreek.com/2014/03/leetcode-find-minimum-in-rotated-sorted-array-ii-java/
public class Solution {
		   public int findMin(int[] num) {
		    return findMin(num, 0, num.length-1);
		}
		 
		public int findMin(int[] num, int left, int right){
		    if(right==left){
		        return num[left];
		    }
		    if(right == left +1){
		        return Math.min(num[left], num[right]);
		    }
		    // 3 3 1 3 3 3
		 
		    int middle = (right-left)/2 + left;
		    // already sorted
		    if(num[right] > num[left]){
		        return num[left];
		    //right shift one
		    }else if(num[right] == num[left]){
		        return findMin(num, left+1, right);
		    //go right    
		    }else if(num[middle] >= num[left]){
		        return findMin(num, middle, right);
		    //go left    
		    }else{
		        return findMin(num, left, middle);
		    }
		}