力扣34在排序数组中查找元素的第一个和最后一个位置:思路分析+图文详解+代码实现(最靠左索引,最靠右索引)

简介: 力扣34在排序数组中查找元素的第一个和最后一个位置:思路分析+图文详解+代码实现(最靠左索引,最靠右索引)

第一部分:题目描述

🏠 链接:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

⭐ 难度:中等

第二部分:思路分析

需要使用 最靠左索引最靠右索引 解决该问题。

  • 最靠左索引:搜索目标值为 target 且 索引最小的索引位置
  • 最靠右索引:搜索目标值为 target 且 索引最大的索引位置

📝 以 最靠左索引 为例来说明:

  • 我们知道普通的二分查找是找到一个 目标值 就停止搜索,返回 中间索引 就可以了。
  • 但这里我们需要查找 索引最小的索引位置,那么即使查找到了一个目标值不能直接返回,应该记录下当前的目标值对应的索引,即中间索引mid。

  • 同时,查找到了这个目标值,我们应该缩小搜索的右边范围,既查找 当前mid索引 左边的范围。
  • 即 需要设置 right = mid - 1

同理,最靠右索引也需要记录 每次查找到的索引,同时缩小搜索的左边范围,即设置 left = mid + 1

第三部分:代码实现

class Solution {
    public int[] searchRange(int[] nums, int target) {
        // 查找最小索引
        int minIndex = searchMinIndex(nums, target);
        // 如果未搜索到说明数组不存在目标值
        if (minIndex == -1) {
            return new int[]{-1, -1};
        }
        // 查找最大索引
        int maxIndex = searchMaxIndex(nums, target);
        return new int[]{minIndex, maxIndex};
    }
    private int searchMinIndex(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        // 记录最小索引
        int minIndex = -1;
        int mid;
        while (left <= right) {
            // 无符号右移 代替 /2 操作,避免 left + right 的超出 int能取的最大值
            mid = (left + right) >>> 1;
            if (target < nums[mid]) {
                // 如果 目标值 小于 中间值
                right = mid - 1;
            } else if (nums[mid] < target) {
                // 如果 目标值 大于 中间值
                left = mid + 1;
            } else {
                // 记录当前中间索引为最小索引
                minIndex = mid;
                // 缩小右范围,以便能向左查找更小的索引
                right = mid - 1;
            }
        }
        return minIndex;
    }
    private int searchMaxIndex(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        // 记录最大索引
        int maxIndex = -1;
        int mid;
        while (left <= right) {
            // 无符号右移 代替 /2 操作,避免 left + right 的超出 int能取的最大值
            mid = (left + right) >>> 1;
            if (target < nums[mid]) {
                // 如果 目标值 小于 中间值
                right = mid - 1;
            } else if (nums[mid] < target) {
                // 如果 目标值 大于 中间值
                left = mid + 1;
            } else {
                // 记录当前中间索引为最大索引
                maxIndex = mid;
                // 缩小左范围,以便能向右查找更大的索引
                left = mid + 1;
            }
        }
        return maxIndex;
    }
}
public int[] searchRange(int[] nums, int target) {
        // 查找最小索引
        int minIndex = searchMinIndex(nums, target);
        // 如果未搜索到说明数组不存在目标值
        if (minIndex == -1) {
            return new int[]{-1, -1};
        }
        // 查找最大索引
        int maxIndex = searchMaxIndex(nums, target);
        return new int[]{minIndex, maxIndex};
    }
    private int searchMinIndex(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        // 记录最小索引
        int minIndex = -1;
        int mid;
        while (left <= right) {
            // 无符号右移 代替 /2 操作,避免 left + right 的超出 int能取的最大值
            mid = (left + right) >>> 1;
            if (target < nums[mid]) {
                // 如果 目标值 小于 中间值
                right = mid - 1;
            } else if (nums[mid] < target) {
                // 如果 目标值 大于 中间值
                left = mid + 1;
            } else {
                // 记录当前中间索引为最小索引
                minIndex = mid;
                // 缩小右范围,以便能向左查找更小的索引
                right = mid - 1;
            }
        }
        return minIndex;
    }
    private int searchMaxIndex(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        // 记录最大索引
        int maxIndex = -1;
        int mid;
        while (left <= right) {
            // 无符号右移 代替 /2 操作,避免 left + right 的超出 int能取的最大值
            mid = (left + right) >>> 1;
            if (target < nums[mid]) {
                // 如果 目标值 小于 中间值
                right = mid - 1;
            } else if (nums[mid] < target) {
                // 如果 目标值 大于 中间值
                left = mid + 1;
            } else {
                // 记录当前中间索引为最大索引
                maxIndex = mid;
                // 缩小左范围,以便能向右查找更大的索引
                left = mid + 1;
            }
        }
        return maxIndex;
    }


相关文章
|
1天前
|
算法
leetcode代码记录(寻找两个正序数组的中位数
leetcode代码记录(寻找两个正序数组的中位数
9 2
|
1天前
|
索引
leetcode代码记录(最长重复子数组
leetcode代码记录(最长重复子数组
5 0
|
1天前
leetcode代码记录(下一个更大元素 II
leetcode代码记录(下一个更大元素 II
4 0
|
1天前
|
索引
leetcode代码记录(下一个更大元素 I
leetcode代码记录(下一个更大元素 I
4 0
|
1天前
leetcode代码记录(两个数组的交集
leetcode代码记录(两个数组的交集
7 1
|
1天前
leetcode代码记录(最大子数组和
leetcode代码记录(最大子数组和
8 2
|
2天前
leetcode代码记录(移除链表元素
leetcode代码记录(移除链表元素
6 0
|
2天前
leetcode代码记录(移除元素
leetcode代码记录(移除元素
6 0
|
1天前
|
算法 C++
【刷题】Leetcode 1609.奇偶树
这道题是我目前做过最难的题,虽然没有一遍做出来,但是参考大佬的代码,慢慢啃的感觉的真的很好。刷题继续!!!!!!
6 0
|
1天前
|
算法 索引
【刷题】滑动窗口精通 — Leetcode 30. 串联所有单词的子串 | Leetcode 76. 最小覆盖子串
经过这两道题目的书写,相信大家一定深刻认识到了滑动窗口的使用方法!!! 下面请大家继续刷题吧!!!
7 0

热门文章

最新文章