mybloger

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

63、在排序数组中查找元素的第一个位置和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

输入:nums = [], target = 0
输出:[-1,-1]
class Solution {
    public int[] searchRange(int[] nums, int target) {
        if (nums.length == 0) {
            return new int[]{-1,-1};
        }
          
        int[] ans = new int[2];
        int l = 0,r = nums.length - 1;
        while (l < r) {
            int mid = l + (r - l + 1)  / 2;
            if (nums[mid] <= target) {
                l = mid;
            }else {
                r = mid - 1;
            }
        }
        if (nums[l] == target) ans[1] = l;

        l = 0;
        r = nums.length - 1;

        while (l < r) {
            int mid = l + (r - l) / 2;
            if (nums[mid] >= target) {
                r = mid;
            }else {
                l = mid + 1;
            }
        }
        if (nums[l] == target) ans[0] = l;

        if (nums[ans[0]] != target) {
            ans[0] = -1;
            ans[1] = -1;
        }

        return ans;
    }
}

64、寻找旋转排序数组中的最小值

已知一个长度为 n 的数组,预先按照升序排列,经由 1n旋转 后,得到输入数组。例如,原数组 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) 的算法解决此问题。

public class Solution {
    public int findMin(int[] nums) {
        int n = nums.length;             // 数组长度
        if (n == 0) {                   // 如果数组为空,题意中一般不允许,可抛异常处理
            throw new IllegalArgumentException("数组不能为空");
        }
        int left = 0, right = n - 1;    // 初始化左、右指针
        while (left < right) {          // 当 left < right 时继续循环
            int mid = (left + right) >>> 1;  // 计算中点索引,使用无符号右移防止溢出
            if (nums[mid] > nums[right]) {
                // 中点元素比最右边元素大,说明旋转点在右侧,最小值在 mid 右边
                left = mid + 1;        // 排除 mid 及其左侧部分
            } else {
                // 否则说明中点右侧有序,最小值在 mid 左侧或就是 mid
                right = mid;           // 包括 mid 在内,缩小右边界
            }
        }
        // 循环结束时 left == right,指向最小值
        return nums[left];
    }
}
posted on 2025-07-27 20:41  万能包哥  阅读(8)  评论(0)    收藏  举报