前端刷题路-Day37:搜索旋转排序数组(题号33)

搜索旋转排序数组(题号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

示例 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

进阶:你可以设计一个时间复杂度为 O(log n) 的解决方案吗?

链接

leetcode-cn.com/problems/se…

解释

还记得Day35那篇文章么(传送们:Day35:搜索旋转排序数组 II(题号81)。这题是那一题的简单版本,里面不带重复数字的。

不带重复数字就简单一些了,下面好好分析一下。

首先,数组是升序的,由小到大,在某一个点旋转后,数组就会变成两个部分,一部分是从小到大,一部分从大到小。还有一种可能性是数组不旋转,一直都是从小到大。

那么这题就可以用双指针来做了,可以说是普通双指针的变种吧。

首先定位左右指针,一个在前一个在后,开启循环,条件是是左指针小于等于右指针。

下面是循环步骤:

  1. 拿到mid,取左右指针和的一半
  2. 比较左指针和mid的大小
    1. 如果左指针小于等于mid,证明这个区间是个递增区间,判断mid是否在这个区间内
      • 在,将右指针放到mid左边一位,也就是mid-1
      • 不在,将左指针放到mid右一位,也就是mid+1
    2. 如果左指针大于等于mid,证明从mid到右指针区间是递增区间,判断mid是否在这个区间内
      • 在,将左指针放到mid右一位,也就是mid+1
      • 不在,将右指针放到mid左边一位,也就是mid-1

在循环完成后直接返回-1就行了,因为这证明没找到target,直接GG。

整体逻辑还是比较简单的,?看看具体的代码。

自己的答案(二分)

var search = function(nums, target) {
  var left = 0
      right = nums.length - 1
  while (left <= right) {
    var mid = ~~((left + right) / 2)
    if (nums[mid] === target) return mid
    if (nums[left] <= nums[mid]) {
      if (nums[left] <= target && nums[mid] > target) {
        right = mid - 1
      } else {
        left = mid + 1
      }
    } else {
      if (nums[right] >= target && nums[mid] < target) {
        left = mid + 1
      } else {
        right = mid - 1
      }
    }
  }
  return -1
};
复制代码

这里有几个地方需要注意:

  1. 不需要特别处理为1的情况,如果数组长度只有1,那么mid就会变成这个唯一的元素,接下来不管是left会自增,然后超过right,终止循环。
  2. 数组长度为0的情况也不需要处理,因为题目规定数组长度最少为1。
  3. 注意处理边界情况,注意区分>=<,不能都用>=<=

别的也就没啥了,具体的逻辑在解释部分已经说过了。

更好的方法

PS:想查看往期文章和题目可以点击下面的链接:

这里是按照日期分类的?

前端刷题路-目录(日期分类)

经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的?

前端刷题路-目录(题型分类)

有兴趣的也可以看看我的个人主页?

Here is RZ

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享