剑指 Offer 53 - I. 在排序数组中查找数字 I

185 阅读1分钟

剑指 Offer 53 - I. 在排序数组中查找数字 I

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

1、题目

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

实例1

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

输出: 2

实例2

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

输出: 0

提示

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

2、思路

方法一

  1. 基于二分法的思想,先找到中间的位置
  2. 从中间的位置,定义两个指针,一个指针往前查找,一个指针往后查找
  3. 这里需要的就是判定条件,只有当M为题目中所给target才能进行,即 nums[M] == target

方法二

  1. 基于第一种方法,可以想到当查找到 target 元素的数字后,此时我们的R指向的是target后面地址,
  2. 基于方法一,我们可以利用类似于步骤1的方法来进行
  3. 这是我们就想到要封装一个方法来进行 target-1 的R指向地址
  4. target 的 R指向的位置 减去 target - 1 的 R指向的位置就可以得到结果了

3、代码

第一次commit AC

class Solution {
    public int search(int[] nums, int target) {
        //保证数字存在
        if(nums == null || nums.length == 0) return 0;
        int L = 0;
        int R = nums.length - 1;
        int count = 0;//统计个数
        int M = 0;
        while(L <= R){
            //向下取整确保不越界
            M = (R + L) >> 1;
            if (nums[M] == target){
                int l = M;
                int r = M + 1;
                //从与该数相等的位置开始向前查找
                while(l>=0) {
                    if(nums[l--]==target) count++;
                }
                //从与该数相等的位置开始向后查找
                while(r<=R) {
                    if(nums[r++]==target) count++;
                }
                //跳出循环
                return count;
            }else if(nums[M] < target){
                L = M + 1;
            }else{
                R = M - 1;
            }
        }
        return count;
    }
}

时间复杂度:二分找到中心点,需要继续往前、往后扫描。复杂度为 O(n) 空间复杂度:O(1)

第二次commit AC

class Solution {
    public int search(int[] nums, int target) {
        return help(nums, target) - help(nums, target - 1);
    }
    public int help(int arr[], int target){
        int L = 0, R = arr.length - 1;
        while(L <= R){
            int M = (L + R) >> 1;
            if (arr[M] <= target) L = M + 1;
            else R = M - 1;
        }
        return L;
    }
}
  • 时间复杂度:O(logn)
  • 空间复杂度:O(1)

image-20220312225432477

4、总结

该题目的使用二分查找的应用实例,首先要对二分法有所了解。

二分法模板:

public static int binarysearch(int arr[], int L, int R, int target){
    int count = 0;
    int M = (L + R) >> 1;
    if(L > R) return -1;
​
    if (target > arr[M]){
        return binarysearch(arr, M + 1, R, target);
    }else if(target < arr[M]){
        return binarysearch(arr, L, M - 1, target);
    }else {
        return M;
    }
}

❤️‍来自专栏《LeetCode基础算法题》欢迎订阅❤️‍

厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。

对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!

原题链接: 剑指 Offer 53 - I. 在排序数组中查找数字 I