五、搜索旋转排序数组

升序排列的整数数组 nums 在某个点上进行了旋转(例如, [0,1,2,4,5,6,7] 经旋转后可能变为 [4,5,6,7,0,1,2] )。

请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
**

输入**nums = [4,5,6,7,0,1,2], target = 0 输出**:4

刚刚接触这道题时,并不能理解他要做什么,既然要查找目标元素在数组中的索引,直接 indexOf 不就完事了吗,有啥好设计算法的,但是注意题目中的时间复杂度 O (logn),indexOf 时间复杂度是 O (n),不符合题意,所以很自然的能想到二分查找算法的运用

我们随便选择一个点,将数组分为前后两部分
其中**一部分一定是有序的**!!!
知道哪里有序才能确定区间
具体步骤:
我们可以先找出 mid,然后根据 mid 来判断,mid 是在有序的部分还是无序的部分

  1. 假如 mid 小于 start,则 mid 一定在右边有序部分
  2. 假如 mid 大于等于 start, 则 mid 一定在左边有序部分 (注意等号的考虑)

然后我们继续判断 target 在哪一部分, 我们就可以舍弃另一部分了

[5~6]搜索旋转排序数组 - 图1

  1. var search = function (nums, target) {
  2. let left = 0;
  3. let right = nums.length - 1;
  4. while (left <= right) {
  5. const mid = left + ((right - left) >> 1);
  6. if (nums[mid] === target) return mid;
  7. // 找有序的那部分
  8. // [left, mid]有序
  9. if (nums[left] <= nums[mid]) {
  10. // target在左边有序的里面
  11. if (target >= nums[left] &&
  12. target < nums[mid]) right = mid - 1;
  13. // target不在左边有序的里面,left要收缩
  14. else left = mid + 1;
  15. }
  16. // [mid, right]有序
  17. else if (nums[mid] < nums[left]) {
  18. // target在右边有序里面
  19. if (target > nums[mid] &&
  20. target <= nums[right]) left = mid + 1;
  21. // 不在右边有序的里面
  22. else right = mid - 1;
  23. }
  24. }
  25. return -1
  26. };

六、搜索旋转排序数组II

假设按照升序排序的数组在预先未知的某个点上进行了旋转。
例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2]

有重复元素

编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。

示例 1: 输入: nums = [2,5,6,0,0,1,2], target = 0 输出: true

示例 2: 输入: nums = [2,5,6,0,0,1,2], target = 3 输出: false

  1. /*
  2. * @lc app=leetcode id=33 lang=javascript
  3. *
  4. * [33] Search in Rotated Sorted Array
  5. */
  6. /**
  7. * @param {number[]} nums
  8. * @param {number} target
  9. * @return {number}
  10. */
  11. const search = (nums, target) => {
  12. let left = 0, right = nums.length -1
  13. while(left<=right) {
  14. let mid = (left+right)>>>1
  15. if(nums[mid] === target) return true;
  16. // 存在重复数字无法判断哪边是递增的,将左端右移一位
  17. if(nums[left] == nums[mid]) ++ left;
  18. else if(nums[mid] <= nums[right]){
  19. // 右边递增
  20. if(target > nums[mid] &&
  21. target <= nums[right]) left = mid + 1;
  22. else right = mid - 1;
  23. }
  24. else {
  25. // 左边递增
  26. if(target < nums[mid] &&
  27. target >= nums[left]) right = mid - 1;
  28. else left = mid + 1
  29. }
  30. }
  31. return false
  32. };