153.寻找旋转排序数组中的最小值Ⅰ
题目详情:
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如:原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 2 次,则可以得到 [2,4,5,6,7,0,1]
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
给定一个元素值 互不相同 升序排列的数组 nums ,并按上述情形进行了多次旋转。请找出并返回数组中的 最小元素 。
解析:经过旋转的数组,前半段满足 >=nums[0],后半段不满足 >=nums[0]。因此,通过二分找到旋转点,然后通过旋转点找到全局最小值。
class Solution {
public int findMin(int[] nums] {
int n = nums.length;
int low = 0, high = n - 1;
//寻找旋转点
while (low < high) {//循环条件只要满足low<high就说明没有找到最小值
int mid = low + high + 1 >> 1;
if (nums[mid] >= nums[0]) {//判断最小值是在而分段的前一段还是后一段
low = mid;
} else {
high = mid - 1;
}
}
//如果high<n+1,说明经过了旋转(不是原数组),最小值经过旋转循环过后一定在high+1位置;
//否则nums未旋转,或者旋转过后保持原数组,则最小值在0处
return high + 1 < n ? nums[high+1] : nums[0];
}
}
154.寻找旋转排序数组中的最小值Ⅱ
题目详情:
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]
若旋转 7 次,则可以得到 [0,1,4,4,5,6,7]
注意:所谓的旋转其实就是[将某个下标前面的所有数整体移到后面,使得数组从整体升序变成分段升序]
给定一个可能存在 重复 元素的升序排列数组 nums ,并按上述情形进行了多次旋转。请找出并返回数组中的 最小元素 。
不同点: 与上一题的不同之处在于本题可以元素重复,这意味着无法直接根据与nums[0]的大小关系将数组划分为二段,即无法通过二分来找旋转点。
因为二分的本质是二段性,而非单调性。只要一段满足某个性质,另一段不满足某个性质,即可用二分。
class Solution {
public int findMin(int[] nums){
int n = nums.length;
int low = 0, high = n - 1;
while (low < high && nums[0] == nums[high]) high--;//恢复二段性
//寻找旋转点
while (low < high) {
int mid = low + high + 1 >> 1;
if (nums[mid] >= nums[0]) {
low = mid;
} else {
high = mid - 1;
}
}
return (high + 1) < n ? nums[high + 1] : nums[0];
}
}
注释:写的不好之处请您纠正,新手小白,期待您来指教!!!