1. 题目
https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/
考察点:
这道题的考察点是二分搜索的应用,你需要掌握如何在旋转排序数组中找到最小值,以及如何判断数组是否旋转过。你还需要注意时间复杂度要求是O(log n),所以不能用线性扫描的方法。你可以参考以下的测试用例
- 输入:nums = [3,4,5,1,2],输出:1
- 输入:nums = [4,5,6,7,0,1,2],输出:0
- 输入:nums = [11,13,15,17],输出:11
- 输入:nums = 1,输出:1
- 输入:nums = [2,1],输出:1
2. 解法
实现的原理
实现的原理是基于旋转排序数组的性质,即数组可以分为两个有序的子数组,而且前一个子数组的所有元素都大于后一个子数组的所有元素。所以,如果我们找到了一个位置mid,使得nums[mid] > nums[end],那么说明最小值一定在mid的右边,否则就在mid的左边或者就是mid。这样我们就可以用二分搜索的方法,不断地缩小搜索范围,直到找到最小值。
思路
是这样的:
- 首先,我定义了两个指针start和end,分别指向数组的首尾。
- 然后,我用一个while循环,不断地缩小start和end之间的距离,直到它们相遇。
- 在每次循环中,我计算了中间位置mid,然后比较nums[mid]和nums[end]的大小。
- 如果nums[mid]大于nums[end],说明最小值在右半部分,所以我把start移动到mid+1的位置。
- 如果nums[mid]小于等于nums[end],说明最小值在左半部分或者就是mid,所以我把end移动到mid的位置。
- 最后,当start和end相遇时,它们就指向了最小值,我返回nums[start]即可。
具体实现
class Solution { public int findMin(int[] nums) { int start = 0; int end = nums.length - 1; while (start < end) { int mid = start + (end - start) / 2; if (nums[mid] > nums[end]) { // 最小值在右半部分 start = mid + 1; } else { // 最小值在左半部分或者就是mid end = mid; } } return nums[start]; // start和end相遇时就是最小值 } }