【LeetCode】每日一题 面试题 10.03. 搜索旋转数组

213 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情

面试题 10.03. 搜索旋转数组

搜索旋转数组。给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同元素,返回索引值最小的一个。

「示例1:」
 输入: arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 5
 输出: 8(元素5在该数组中的索引)
「示例2:」
 输入:arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 11
 输出:-1 (没有找到)
「提示:」
 arr 长度范围在[1, 1000000]之间

解题思路

// 第一种
先找到遍历的位置,如果target比数组的第一位大,肯定就在数组前面一点,从后往前遍历
如果target比数组第一位小,就从后往前遍历
​
从前往后遍历的时候,找到target就返回,直到遍历到第一个比target大的数字,退出遍历
从后往前遍历的时候,找到和target一样的数字的时候,更新结果下标,直到第一个比target小的数字,退出循环
​
// 第二种
数组一定是两段分别递增
在两段上分别用二分搜索查找
先找左边的段,再找右边的段(方便返回最小的索引)

代码实现

/**
 * @param {number[]} arr
 * @param {number} target
 * @return {number}
 */
var search = function(arr, target) {
    const len = arr.length
    if (target >= arr[0]) {
        // 从前往后
        let l = 0
        while(l < len) {
            if (arr[l] === target) return l
            if (arr[l] > target) break
            l++
        }
        return -1
    } else {
        // 从后往前
        let l = len - 1, res = -1
        while (l >= 0) {
            if (arr[l] === target) res = l
            if (arr[l] < target) break
            l--
        }
        return res
    }
};
​
// 第二种
var search = function(arr, target) {
​
    // 二分搜索写成模板方便调用,查找左边界的二分搜索
    var biSearch = function(left, right){
        while(left <= right){
            let mid = left + ((right - left)>>1);
            if(arr[mid] >= target){
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return arr[left]===target? left : -1;
    }
​
    // 找到中间的断点区分两段
    let point = 0
    for(let i = 0; i < arr.length-1;i++){
        if(arr[i] <= arr[i+1]){
            point++;
        } else break;
    }
    // 左边进行二分搜索
    let leftRes = biSearch(0, point);
    if(leftRes!== -1) return leftRes; // 左边找到了就返回
    else { // 左边没找到就找右边
        let rightRes = biSearch(point+1, arr.length -1)
        return rightRes;
    }
​
};

如果你对这道题目还有疑问的话,可以在评论区进行留言;