算法小知识-------02·10-------排序数组找元素

95 阅读2分钟

这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战

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

该题出自力扣的34题 —— 在排序数组中查找元素的第一个和最后一个位置【中等题】

审题

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶: 你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

  • 从题意就是简单题的意思,给出一个有序数组,并且找出其中的目标元素的下标,目标元素可能不止存在一个,所以返回一个数组,存出现的第一个和最后一个。
  • 实现方式也很多,但是需要注意题意最后的进阶,用时间复杂度O(log n)
  • 简单粗暴for循环
    • 直接for循环,用两个变量分别记录下标
    • 时间复杂度O(n),遍历整个数组
  • 因为是有序数组,所以大可不必用到遍历整个数组;二分查找更适合这种有序数组
    • 判断数组是否为空
    • 用两个变量统计下标,下标是目标数的第一个和最后一个。
    • 调用二分方法
    • 二分方法 稍微调整,返回目标数的下一位初次出现位置

编码

  • 暴力循环
   public int[] searchRange(int[] nums, int target) {
       int[] a = new int[]{-1,-1};
       if (nums.length == 0)return a;
       for (int i = 0;i<nums.length;i++) {
           if (nums[i] == target && a[0] == -1)a[0] = i;
           if(nums[i] == target)a[1] = i;
       }
       return a;

   }

1644484420.jpg

  • 二分查找
class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] a = new int[]{-1,-1};
        if (nums.length == 0)return a;
        int left = binarySearch(nums,target-1);
        int right = binarySearch(nums,target)-1;
        if (right>=left && nums[left] == target){
            a[0] = left;
            a[1] = right;
        }
        return a;
    }
       public int binarySearch(int[] nums,int target){
        int left = 0,right = nums.length -1,ans = nums.length;
        while(right>=left){
            int mid = left+(right - left)/2;
            if (nums[mid] >target){
                right = mid -1;
                ans = mid;
            }else {
                left = mid +1;
            }
        }
        return ans;
    }
}

image.png

总结

对于二分的理解还不够娴熟,还是没有办法在看到题意的时候冒出二分的想法,直到完成题目提交后,才醒悟过来。并且容易卡在对于二分的初步理解,也就是背模板,无法灵活变通,例如题意里面的查找下一位的最初位置,返回 mid;