85 lines
2.7 KiB
Go
85 lines
2.7 KiB
Go
package top100liked
|
||
|
||
import "testing"
|
||
|
||
// https://leetcode.cn/problems/search-in-rotated-sorted-array/?envType=study-plan-v2&envId=top-100-liked
|
||
// 33. 搜索旋转排序数组
|
||
//
|
||
// 整数数组 `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`
|
||
|
||
// search 在旋转升序数组中查找 target,返回下标或 -1。
|
||
//
|
||
// 思路:一次二分,不需要先找旋转点。
|
||
// 取 mid 后,[lo, mid] 和 [mid, hi] 必有一半是有序的:
|
||
// - 若 nums[lo] <= nums[mid],左半有序;判断 target 是否落在 [nums[lo], nums[mid]],
|
||
// 是则搜左半,否则搜右半。
|
||
// - 否则右半有序;判断 target 是否落在 [nums[mid], nums[hi]],
|
||
// 是则搜右半,否则搜左半。
|
||
//
|
||
// 时间 O(log n),空间 O(1)。
|
||
func search(nums []int, target int) int {
|
||
lo, hi := 0, len(nums)-1
|
||
for lo <= hi {
|
||
mid := lo + (hi-lo)/2
|
||
if nums[mid] == target {
|
||
return mid
|
||
}
|
||
// 左半 [lo, mid] 有序
|
||
if nums[lo] <= nums[mid] {
|
||
if nums[lo] <= target && target < nums[mid] {
|
||
hi = mid - 1
|
||
} else {
|
||
lo = mid + 1
|
||
}
|
||
} else { // 右半 [mid, hi] 有序
|
||
if nums[mid] < target && target <= nums[hi] {
|
||
lo = mid + 1
|
||
} else {
|
||
hi = mid - 1
|
||
}
|
||
}
|
||
}
|
||
return -1
|
||
}
|
||
|
||
func TestSearch(t *testing.T) {
|
||
cases := []struct {
|
||
name string
|
||
nums []int
|
||
target int
|
||
want int
|
||
}{
|
||
{"example1", []int{4, 5, 6, 7, 0, 1, 2}, 0, 4},
|
||
{"example2", []int{4, 5, 6, 7, 0, 1, 2}, 3, -1},
|
||
{"example3", []int{1}, 0, -1},
|
||
{"example4", []int{1}, 1, 0},
|
||
}
|
||
for _, c := range cases {
|
||
t.Run(c.name, func(t *testing.T) {
|
||
got := search(c.nums, c.target)
|
||
if got != c.want {
|
||
t.Errorf("got %v, want %v", got, c.want)
|
||
}
|
||
})
|
||
}
|
||
}
|