• Leetcode OJ: Search in Rotated Sorted Array I/II


    对于有序数组进行查找我们可以用二分查找,可以参考我之前写的 Search Insert Position

    但如果把这个排序的数组当成一个环,然后做一个旋转操作后再截断,再进行查找又会是什么情况呢?且看下文分解。

    Suppose a sorted array is rotated at some pivot unknown to you beforehand.

    (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

    You are given a target value to search. If found in the array return its index, otherwise return -1.

    You may assume no duplicate exists in the array.

    分成了两部分,而且是分别排序的,我们是不是也可以用二分呢?怎么用?先看看以下分析:

    如果二分查找中的mid是落在左侧,则有A[mid] > A[begin] > A[end-1],否则有A[mid] < A[end - 1] < A[begin]

    在我们确定是在哪一侧之后,那问题就变得简单了。

    在左侧时,只需要比较target与A[begin];在右侧时,只需要比较target与A[end]。

    具体代码吧:

     1 class Solution {
     2 public:
     3     int search(int A[], int n, int target) {
     4         int begin = 0, end = n;
     5         int mid;
     6         while (begin < end) {
     7             mid = begin + ((end - begin) >> 1);
     8             if (A[mid] == target)
     9                 return mid;
    10             if (A[mid] > A[begin]) {
    11                 if (A[mid] < target) {
    12                     begin = mid + 1;
    13                 } else {
    14                     if (A[begin] < target)
    15                         end = mid;
    16                     else if (A[begin] > target)
    17                         begin = mid + 1;
    18                     else 
    19                         return begin;
    20                 }
    21             } else {
    22                 if (A[mid] > target) {
    23                     end = mid;
    24                 } else {
    25                     if (A[end - 1] < target)
    26                         end = mid;
    27                     else if (A[end-1] > target)
    28                         begin = mid + 1;
    29                     else
    30                         return end - 1;
    31                 }
    32             }
    33         }
    34         return -1;
    35     }
    36 };

    对于这道题算是完美解决了,细心的同学们可能会发现这题的说明里面特意提到no duplicate,那如果有duplicate又怎样了?于是有了这题的变型:

    Follow up for "Search in Rotated Sorted Array":
    What if duplicates are allowed?

    Would this affect the run-time complexity? How and why?

    Write a function to determine if a given target is in the array.

    有重复元素又会怎样?我们上面解法的关键在于我们能区分得出mid点是在左侧还是右侧,那如果存在重复的元素呢?且看下图

    当mid上的点与begin与end-1上的点都相等时,你无法判断是左侧还是右侧!

    那怎么解决这个问题呢?我们想想,合并重复元素不就回到之前的问题了?

    不过这里我们不用遍历一遍数组然后把重复的元素合并,一方面这样会破坏数组,另一方面,我们还有更高明的办法。

    利用好排序的特点,我们只需要begin重复的往后移,end重复的往前移即可。且看代码:

     1 class Solution {
     2 public:
     3     bool search(int A[], int n, int target) {
     4         int begin = 0, end = n, mid;
     5         while (begin < end) {
     6             // 检测首尾重复的并移动
     7             while (begin < end - 1 && A[begin] == A[begin + 1])
     8                 ++begin;
     9             while (end > begin + 1 && A[end - 1] == A[end - 2])
    10                 --end;
    11             mid = begin + ((end - begin) >> 1);
    12             if (A[mid] == target)
    13                 return true;
    14             if (A[mid] > A[begin]) {
    15                 if (A[mid] < target) {
    16                     begin = mid + 1;
    17                 } else {
    18                     if (A[begin] > target) {
    19                         begin = mid + 1;
    20                     } else if (A[begin] < target) {
    21                         end = mid;
    22                     } else {
    23                         return true;
    24                     }
    25                 }
    26             } else {
    27                 if (A[mid] > target) {
    28                     end = mid;
    29                 } else {
    30                     if (A[end - 1] > target) {
    31                         begin = mid + 1;
    32                     } else if (A[end - 1] < target) {
    33                         end = mid;
    34                     } else {
    35                         return true;
    36                     }
    37                 }
    38             }
    39         }
    40         return false;
    41     }
    42 };
  • 相关阅读:
    javascript类的封装『转』
    闭包概念
    继承
    理解面向对象
    cookie的使用
    开园啦。。。
    Myslq 之常用命令
    Myslq 之修改提示符
    Myslq 之登陆、退出
    Javascript 之 Number
  • 原文地址:https://www.cnblogs.com/flowerkzj/p/3619335.html
Copyright © 2020-2023  润新知