“这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战”
一、在旋转有序的数组中搜索
(一)、题目需求
给你一个升序排列的整数数组 nums ,和一个整数 target 。
假设按照升序排序的数组在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
示例 3:
输入:nums = [1], target = 0
输出:-1
(二)、解法
public class Solution {
public static void main(String[] args) {
System.out.println(Solution.search(new int[]{4, 5, 6, 7, 0, 1, 2}, 0));
}
public static int search(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0;
int end = nums.length - 1;
int mid;
while (start + 1 < end) {
mid = start + (end - start) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[mid] > nums[start]) {
if (nums[mid] >= target && target >= nums[start]) {
end = mid;
} else {
start = mid;
}
} else {
if (nums[mid] <= target && target <= nums[end]) {
start = mid;
} else {
end = mid;
}
}
}
if (nums[start] == target) {
return start;
}
if (nums[end] == target) {
return end;
}
return -1;
}
}
(三)、代码解析
1、设置开始指针、结束指针、中间指针
int start = 0;
int end = nums.length - 1;
int mid;
2、计算mid值,通过该方式计算可避免大数的情况
mid = start + (end - start) / 2;
if (nums[mid] == target) {
return mid;
}
3、进行判断:
假如中间值大于开始值:则意味着旋转发生在中间值的后面。
情况1:目标值小于中间值,同时目标值大于开始值。所以寻找的目标位于中间值的前面,因此将结束值往前移动。
情况2:目标值大于中间值。所以寻找的目标位于中间值的后面,因此将开始值往后移动。
情况3:目标值小于中间值,同时目标值小于开始值。所以寻找的目标位于中间值的后面,因此将开始值往后移动。
假如中间值小于开始值:则意味着旋转发生在中间值的前面。
情况1:目标值大于中间值,同时目标值小于开始值。所以寻找的目标位于中间值的后面,因此将开始值往后移动。
情况2:目标值小于中间值。所以寻找的目标位于中间值的前面,因此将结束值往前移动。
情况3:目标大于中间值,同时目标值大于开始值。所以寻找的目标位于中间值的前面,因此将结束值往前移动。
if (nums[mid] > nums[start]) {
if (nums[mid] >= target && target >= nums[start]) {
end = mid;
} else {
start = mid;
}
} else {
if (nums[mid] <= target && target <= nums[end]) {
start = mid;
} else {
end = mid;
}
}
二、在旋转有序的数组中寻找最小数值
(一)、题目需求
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请找出其中最小的元素。
你可以假设数组中不存在重复元素。
示例 1:
输入: [3,4,5,1,2]
输出: 1
示例 2:
输入: [4,5,6,7,0,1,2]
输出: 0
(二)、解法
public class Solution {
public static void main(String[] args) {
Solution.findMin(
new int[]{5, 1, 2, 3, 4}
);
}
public static int findMin(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}
if (nums[0] <= nums[nums.length - 1]) {
return nums[0];
}
int start = 0;
int end = nums.length - 1;
int mid;
while (start + 1 < end) {
mid = start + (end - start) / 2;
if (nums[mid] >= nums[end]) {
start = mid;
} else {
end = mid;
}
}
return nums[start] <= nums[end] ? nums[start] : nums[end];
}
}
(三)、代码解析
1、首先判断是否有序,如果第一个值小于等于最后一个值,说明无发生旋转,直接返回第一个值即可。
if (nums[0] <= nums[nums.length - 1]) {
return nums[0];
}
2、设置开始指针、结束指针、中间指针
int start = 0;
int end = nums.length - 1;
int mid;
3、计算中间值,同时判断中间值和结束值的大小。
情况1:中间值大于结束值,说明旋转发生在中间值后面,所以将开始值往后移动。
情况2:中间值小于结束值,说明旋转发生在中间值前面,所以将结束值往前移动。
while (start + 1 < end) {
mid = start + (end - start) / 2;
if (nums[mid] >= nums[end]) {
start = mid;
} else {
end = mid;
}
}