O(n)的算法就不说了,这题主要考查的是 O(logn)的算法。
有序数组容易想到使用二分查找解决,这题就是在二分基础上做一些调整。数组只有一次翻转,可以知道原有序递增数组被分成两部分,这俩部分都是有序递增的(这题只需要考虑有序数组的递增情况)。
假如翻转后的数组以第 x 个结点分为两部分 A[0..x] 和 A[x+1..n]。则 A[0..x] 这一段是有序递增的, A[x+1..n] 这一段也是有序递增的。并且因为原数组是有序递增的,A[0..x] 中所有数都会大于 A[x+1..n] 中的任何数。所以我们其实就是需要找到结点 A[x+1],这个结点的值就是最小值。
考虑数组 A[i..j],中间结点 m (m = (i + j ) / 2)。
A[i] < A[j]:数组是递增的,说明已经找到 x 结点,并且 x 等于 i。
A[i] >= A[j]:数组不是递增的,说明 x 结点还没有找到,这时对比中间结点 A[m]
A[m] > A[i]: 则数组中 A[i..m] 这一段是有序递增的,翻转结点 x 定不会在这一段中,这时我们只需要考虑 A[m+1..j] 这一段。
A[m] < A[i]:说明翻转结点 x 在 A[i..m]中。
另外特别考虑只有一个元素的情况。
public class Solution { public int findMin(int[] num) { int left = 0; int right = num.length - 1; while(left < right) { if(num[left] < num[right]) { return num[left]; } int mid = left + (right-left)/2; if(num[left] <= num[mid]) { left = mid + 1; } else { right = mid; } } return num[left]; } }
http://orzorz.me/learn/lesson.htm?lessonId=106
递归
Thoughts:
- If the array just has one element, then return the element.
- If the array has two elements, then return the smaller one.
- If the left most element is smaller than the right most element, then we can know the array is sorted like never be rotated. Just return the left one.
- By the method of Binary Search, we get the middle element of array, a[mid]. If a[mid] > a[left], then the left half of array is sorted. we then search the right half, including a[mid]. Otherwise we search the left half, including a[mid].
public class Solution { public int findMin(int[] A) { return helper(A, 0, A.length-1); } public static int helper(int[] a, int left, int right){ //one element if(left == right){ return a[left]; } //two elements if(left == right-1){ return a[left]<a[right]? a[left]: a[right]; } //the array is ordered if(a[left] < a[right]){ return a[left]; } int mid = (left+right)/2; if(a[mid] >= a[left]){ return helper(a, mid, right); }else{ return helper(a, left, mid); } } }
https://chesterli0130.wordpress.com/2012/10/20/finding-the-minimum-in-a-sorted-rotated-array/
时间: 2024-10-05 04:24:24