Search in Rotated Sorted Array
LeetCode https://leetcode.cn/problems/search-in-rotated-sorted-array/
题目描述
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
示例 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
提示:
- 1 <= nums.length <= 5000
- -10^4 <= nums[i] <= 10^4
- nums 中的每个值都 独一无二
- 题目数据保证 nums 在预先未知的某个下标上进行了旋转
- -10^4 <= target <= 10^4
解题报告
!!!!很重要的一道题!!!!
两种情况,一种 middle 在第一段上升区间,另一种是 middle 在第二段上升区间。
分情况讨论。确定答案在哪个区间,然后切一刀。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Solution {
public 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[start] < nums[mid]) {
if (nums[start] <= target && target <= nums[mid]) {
end = mid;
} else {
start = mid;
}
} else {
if (nums[mid] <= target && target <= nums[end]) {
start = mid;
} else {
end = mid;
}
}
} // end while loop
if (nums[start] == target) {
return start;
}
if (nums[end] == target) {
return end;
}
return -1;
} // end search
} // end Solution
Find Minimum in Rotated Sorted Array
Leetcode https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/
题目描述
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0, 1, 2, 4, 5, 6, 7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4, 5, 6, 7, 0, 1, 2]
若旋转 7 次,则可以得到 [0, 1, 2, 4, 5, 6, 7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
示例 1:
输入:nums = [3, 4, 5, 1, 2]
输出:1
解释:原数组为 [1, 2, 3, 4, 5] ,旋转 3 次得到输入数组。
示例 2:
输入:nums = [4, 5, 6, 7, 0, 1, 2] 输出:0
解释:原数组为 [0, 1, 2, 4, 5, 6, 7] ,旋转 4 次得到输入数组。
示例 3:
输入:nums = [11, 13, 15, 17]
输出:11
解释:原数组为 [11, 13, 15, 17] ,旋转 4 次得到输入数组。
提示:
- n == nums.length
- 1 <= n <= 5000
- -5000 <= nums[i] <= 5000
- nums 中的所有整数 互不相同
- nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转
解题报告
继续二分法搜索,最后的时候找出 start 和 end 哪个最小,返回最小的。
与朴素二分相比,拿 middle 位置的数和 end 位置比较,如果 middle 位置的数大说明最小值藏在右半部分,挪 start 指针到 middle,反之 end 位置的数大说明最小值藏在左半部分,挪 end 到 middle 位置,循环跑到最后的时候 start 和 end 相邻了,取较小者就是最小值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int findMin(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0;
int end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] > nums[end]) {
start = mid;
} else {
end = mid;
}
} // end while loop
return Math.min(nums[start], nums[end]);
} // end findMin
} // end Solution