📑 题目:153. 寻找旋转排序数组中的最小值

🚀 本题 LeetCode 传送门

题目大意

假设按照升序排序的数组在预先未知的某个点上进行了旋转。( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。请找出其中最小的元素。

你可以假设数组中不存在重复元素。

解题思路

  • 给出一个原本从小到大排序过的数组,但是在某一个分割点上,把数组切分后的两部分对调位置,数值偏大的放到了数组的前部。求这个数组中最小的元素。
  • 求数组最小的元素其实就是找分割点,前一个数比当前数大,后一个数比当前数也要大。可以用二分搜索查找,需要查找的两个有序区间。时间复杂度 O(log n)。这一题也可以用暴力解法,从头开始遍历,动态维护一个最小值即可,时间复杂度 O(n)。

代码

  1. package leetcode
  2. // 解法一 二分
  3. func findMin(nums []int) int {
  4. low, high := 0, len(nums)-1
  5. for low < high {
  6. if nums[low] < nums[high] {
  7. return nums[low]
  8. }
  9. mid := low + (high-low)>>1
  10. if nums[mid] >= nums[low] {
  11. low = mid + 1
  12. } else {
  13. high = mid
  14. }
  15. }
  16. return nums[low]
  17. }
  18. // 解法二 二分
  19. func findMin1(nums []int) int {
  20. if len(nums) == 0 {
  21. return 0
  22. }
  23. if len(nums) == 1 {
  24. return nums[0]
  25. }
  26. if nums[len(nums)-1] > nums[0] {
  27. return nums[0]
  28. }
  29. low, high := 0, len(nums)-1
  30. for low <= high {
  31. mid := low + (high-low)>>1
  32. if nums[low] < nums[high] {
  33. return nums[low]
  34. }
  35. if (mid == len(nums)-1 && nums[mid-1] > nums[mid]) || (mid < len(nums)-1 && mid > 0 && nums[mid-1] > nums[mid] && nums[mid] < nums[mid+1]) {
  36. return nums[mid]
  37. }
  38. if nums[mid] > nums[low] && nums[low] > nums[high] { // mid 在数值大的一部分区间里
  39. low = mid + 1
  40. } else if nums[mid] < nums[low] && nums[low] > nums[high] { // mid 在数值小的一部分区间里
  41. high = mid - 1
  42. } else {
  43. if nums[low] == nums[mid] {
  44. low++
  45. }
  46. if nums[high] == nums[mid] {
  47. high--
  48. }
  49. }
  50. }
  51. return -1
  52. }
  53. // 解法三 暴力
  54. func findMin2(nums []int) int {
  55. min := nums[0]
  56. for _, num := range nums[1:] {
  57. if min > num {
  58. min = num
  59. }
  60. }
  61. return min
  62. }