LeetCode 线性表的操作(Search in Rotated Sorted Array )

   

    前面做了下线性表有关的操作,主要是去除线性表中的重复值,(数组和链表),这一篇做两道在线性表中查找的题目。

    LeetCode线性表的操作(Remove Duplicates)



    1.Search in Rotated Sorted Array


    原文链接:点击这里进入


    基本内容:

    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.


    解题思想:

    这题目最一开始想到的肯定是从头开始一个一个的扫描,但是时间复杂度为O(n),这种题目在面试如果采取这样做的话是肯定拿不到offer的。因为是两个部分有序的。全部有序的情况下我们是可以采用二分查找法来做的。这个数组实际上是排序数组的变异品种。
    
    解法一:因为我们在排序好的数组中可以采用二分查找的方法,这个数组其实是两个排序好的数组,我们可以首先找到一个下标值,把这个数组分成两个排序好的数组,然后根据传进来的值去 单个排序好的数组中进行二分查找。这个特定下标前面是一个排序好的数组,后面是一个排序好的数组且这个数组的元素中的任何一个值都比前面的数组中的值小。
    需要考虑下列4种不同的情况:
  •     5,1,2,3,4  (前面的数组只有一个值)
  •     5,6,7,8,1  (后面的数组只有一个值)
  •     5,6,1,2,3 (最正常的情况)
  •     1,2,3,4,5 (已经排序好的情况,也就是未发生旋转,这个需要特殊表示,判断情况是第一个值是否小于最后一个值)
    因为前3种都可以用算法来得到这个值,第4种是未旋转过的,特殊位置可以选在第0个或者最后一个,这个需要我们来特殊处理。
    

    查找特定下标的函数:
int findSpecialPosition( int a[ ], int n )
{
    int begin = 0;
    int end = n - 1;
    int half = ( begin + end ) >> 1;

    //get the pivot
    if( a[ begin ] < a[ end ] )//sorted
        return end;
    while( half + 1 <= end && a[ half ] < a[ half + 1] && begin <= end )
    {
        if( a[ half ] >= a[ begin ] )
        {
            begin = half + 1;
        }
        else
            end = half - 1;
        half = ( begin + end ) >> 1;
    }
    return half;
}
        把4种特殊的情况都测试一遍就可以通过了,下面根据half 返回的值,可以把原数组分为2个排序好的数组,在排序好的数组中进行二分查找法。
     
    合并代码:

    
int SearchBinary( int A[], int begin, int end, int target )
    {
        if( begin <= end )
        {
            int half = ( begin + end ) >> 1;
            while( A[ half ] != target && begin <= end )
            {
                if( A[ half ] > target )
                    end = half - 1;
                else
                    begin = half + 1;
                half = ( begin + end ) >> 1;
            }
            if( A[ half ] == target )
                return half;
            else
                return -1;
        }
        else
            return -1;
    }
    int search(int A[], int n, int target) {
        int begin = 0;
        int end = n - 1;
        int half = ( begin + end ) >> 1;
    
        
        if( A[ begin ] < A[ end ] )//sorted
            SearchBinary( A,0 ,n - 1, target );
        while( half + 1 <= end && A[ half ] < A[ half + 1] && begin <= end )
        {
            if( A[ half ] >= A[ begin ] )
            {
                begin = half + 1;
            }
            else
                end = half - 1;
            half = ( begin + end ) >> 1;
        }
        
    
       
        begin = 0;
        end = n - 1;
    
        if( half + 1 <= end &&A[ half + 1 ] <= target && target <= A[ end ] )
            return SearchBinary( A, half + 1, end, target );
        else
            return SearchBinary( A, begin, half , target );
    }//时间复杂度为o(n),空间复杂度o(1)
    

   解法2:可以把这两步合并起来一起做,将二分查找法利用起来,主要是确定左右边界,根据中间的值确定下一步的查找范围。

    
int search(int A[], int n, int target) {
        int first = 0;
        int end = n - 1;
        int half = ( first + end ) >> 1;
        while( first <= end )
        {
            if( target == A[ half ])
                return half;
            if( A[ half ] >= A[ first ] )//在数组前面部分,
            {
                if( A[ half ] >= target && A[ first ] <= target )
                    end = half;
                else
                    first = half + 1;
            }
            else
            {
                if( A[ half ] <= target && target <= A[ end ] )
                    first = half;
                else
                    end = half - 1;
            }
            half = ( first + end ) >> 1;
        }
        return -1;
        
    }

    
    进阶题目:加一个限制条件

    2.Search in Rotated Sorted Array II


    原文链接:点击这里进入


    基本内容:

    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.

    解题思想:

    
    这里加了一个可以重复,那么会对原先的数组造成什么影响呢? 会造成后面一个数组中可能有数字与前面一个数组中的数相同,也就是说不再是完全排序的了。(后面数组一定比前面的所有值小),获取到a[half]后需要分3种情况来分别看。
  •     a[half] > a[first]  (这说明还是在划分好的前面的那个数组内部)
  •     a[half] < a[first]  (这说明在划分好的后面的那个数组内部)
  •     a[half] == a[first] (这种情况不好说,也可以在前面那个数组,也可以在后面那个数组)

    对于前2种情况,我们和上边的解法一样就可以了,对于后一种相等的情况,我们也不需要进行特殊的处理,直接让first++就可以了,继续往下判断。
 
    OK,代码:
    
  bool search(int A[], int n, int target) {
      int first = 0;
        int end = n - 1;
        int half = ( first + end ) >> 1;
        while( first <= end )
        {
            if( target == A[ half ])
                return true;
            if( A[ half ] > A[ first ] )//在数组前面部分,这个部分是不变的
            {
                if( A[ half ] >= target && A[ first ] <= target )
                    end = half;
                else
                    first = half + 1;
            }
            else if( A[ half ] < A[ first ])
            {
                if( A[ half ] <= target && target <= A[ end ] )
                    first = half;
                else
                    end = half - 1;
            }
            else
                first++;
            half = ( first + end ) >> 1;
        }
        return false;  
    }




    二分查找法的有关题目暂时就写这么多了,如有发现继续添加。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值