本身数组是个有序数组,只是在某个点上发生旋转,我们可以取中位数进行拆分数组,拆分后的数组有一部分一定是有序的,那么我们只要找到有序的那一部分,根据已经给定 target 值进行判断,可以逐步缩小空间。
func Search(nums []int, target int) int { if len(nums) == 0 { return -1 } left, right := 0, len(nums)-1 for left <= right { mid := left + ((right - left) >> 1) midValue := nums[mid] if midValue == target { return mid } // 说明此数组从中位数到右半区是有序的 if midValue < nums[right] { // 说明目标值在(mid,right]之间 if midValue < target && target <= nums[right] { left = mid + 1 // 否则就在[left,mid-1] } else { right = mid - 1 } } else { if midValue > target && target >= nums[left] { right = mid - 1 } else { left = mid + 1 } } } return -1 }
这道题题型和上一题是一样的,只是最终求的是数组中最小值。思路还是去确定最小值在哪个区间。
func findMin(nums []int) int { left, right := 0, len(nums)-1 // 这道题提示不会有重复值,这种情况说明并未旋转 if nums[left] < nums[right] { return nums[left] } for left < right { mid := left + ((right - left) >> 1) // 中位数可能是最小值 if nums[mid] < nums[right] { right = mid // 中位数肯定不是最小值 } else { left = mid + 1 } } return nums[left] }
二分查找并没有唯一的写法。主要看你站在什么样的角度思考,在我看来主要还是边界划分的问题,这是一个核心点以及难点,这个搞清楚,二分也就解了一半。
最后放出一道结尾题目,也是我非常喜欢的一道题,好像也是一道大厂面试高频题?感兴趣的刷去吧。