This commit is contained in:
2026-07-23 16:56:50 +08:00
parent 124ad9afdf
commit 92784ffb0f
36 changed files with 2015 additions and 608 deletions
+74 -33
View File
@@ -1,43 +1,84 @@
package top100liked
import (
"fmt"
"testing"
)
import "testing"
// https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/?envType=study-plan-v2&envId=top-100-liked
// 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`
func findMin(nums []int) int {
if len(nums) == 1 {
return nums[0]
}
if nums[0] < nums[len(nums)-1] {
return nums[0]
}
start := 0
end := len(nums) - 1
for start <= end {
mid := start + (end-start)/2
if mid >= 1 && nums[mid-1] > nums[mid] && mid < len(nums)-1 && nums[mid] < nums[mid+1] {
return nums[mid]
// 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
}
if nums[mid] > nums[end] {
// 最小值在右侧
start = mid + 1
} else {
// 最小值在左侧
end = mid - 1
// 左半 [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
}
}
}
if nums[start] > nums[end] {
return nums[end]
}
return nums[start]
return -1
}
func Test(t *testing.T) {
// fmt.Println(findMin([]int{3, 4, 5, 1, 2}))
// fmt.Println(findMin([]int{3, 1, 2}))
fmt.Println(findMin([]int{2, 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)
}
})
}
}