搜索旋转排序数组|刷题打卡

83 阅读1分钟

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

一、题目描述:

image.png

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

二、思路分析:

暴力解法

直接遍历一遍数组,查看是否出现目标元素。无法完成O(log n)的要求。

  • 时间复杂度:O(N),这里 N 是数组的长度。
  • 空间复杂度:O(1),使用到的临时变量的个数是常数。

二分

参考题解

没想到吧,数组不是严格的单调增或者单调减也可以使用二分查找。 二分的话我们需要找到一个mid位置。判断mid位置和目标元素的大小关系。 但是这道题我们需要根据mid的位置,判断mid位置的值和右边界的大小关系。

image.png

三、AC 代码:

function search($nums, $target) {
        $len_n = count($nums);
        $left = 0;
        $right = $len_n - 1;
        while ($left < $right) {
        //加1是因为下面的判断有left=mid的情况,为了避免死循环
            $mid = $left + (int)(($right - $left + 1) / 2);
            //此时对应第三种情况,我们选择判断mid右边的区间是否包含target
            if ($nums[$mid] < $nums[$right]) {
                if ($target >= $nums[$mid] && $target <= $nums[$right]) {
                    $left = $mid;
                } else {
                    $right = $mid - 1;
                }
            } else {
            //这对应着上图中1,2,3情况。我们选择判断mid左边的区间是否包含target的情况
                if ($target >= $nums[$left] && $target <= $nums[$mid - 1]) {
                    $right = $mid - 1;
                } else {
                    $left = $mid;
                }
            }
        }

//最后循环结束的时候是left==right,所以还需要判断一下最后一个元素是否是target元素。
        return $nums[$left] == $target ? $left : -1;
    }

四、总结:

大家都说,写二分,细节是魔鬼。建议看一下上面的引用题解里提到的博主的二分题解合辑。里面有怎么处理各种边界情况,怎么判断等~