二分查找在array中找数

BinarySearch-33Search in Rotated Sorted Array

问题描述:

Suppose an array sorted in ascending order 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.

问题解析:

1. 本题的意思是: 在一个有序但是被旋转数组中查找一个数字,找到了就返回这个数字的索引,找不到的话就直接返回-1。这个数组中的数字是不重复的。

2. 凡是有序的数组,都应该想到用二分查找来寻找。主要是时间复杂度可以控制在O(log(n))级别。

代码如下:

class Solution {
public:
    // 利用二分查找
    bool binarySearch(vector<int>& nums, int start, int end, int targrt, int &res)
    {
        if(start > end || start<0)
            return false;
        int mid = (start+end)/2;
        if(nums[mid] == targrt)
        {
            res = mid;
            return true;
        }
        else if(nums[mid]>nums[start])
        {
            if(nums[mid]<nums[start]) return binarySearch(nums, start, mid-1, targrt, res);
            else
                return binarySearch(nums, start, mid-1, targrt, res) || binarySearch(nums, mid+1, end, targrt, res);
        }
        else
        {
            if(nums[mid] > nums[start])
                return binarySearch(nums, mid+1, end, targrt, res);
            else
                return binarySearch(nums, start, mid-1, targrt, res) || binarySearch(nums, mid+1, end, targrt, res);
        }
    }
    int search(vector<int>& nums, int target) 
    {
        int len = (int)nums.size();
        if(len == 1 && nums[0] == target) return 0; 
        int res = -1;
        binarySearch(nums, 0, len-1, target, res);
        
        return res;
    }
};


BinarySerach-34Search for a Range

问题描述:

Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,

Given [5, 7, 7, 8, 8, 10] and target value 8,

return [3, 4].

问题解析:

1.本题意思是:在array中找出target,返回这个target在数组中的第一次出现和最后一次出现的索引值。如果target在数组中不存在的话,就返回两个-1。

2.因为是有序数组,使用二分查找来解决,代码如下。

代码如下:

class Solution {
public:
    // 利用二分查找来做
    bool binarySearch(vector<int>& nums, int target, int start, int end, int &l, int &r)
    {
        if(start>end || start<0)
            return false;
        int mid = (start+end)/2;
        if(nums[mid] == target)
        {
            int ll, rr;
            if(binarySearch(nums, target, start, mid-1, ll, rr))
                l = ll;
            else
                l = mid;
            if(binarySearch(nums, target, mid+1, end, ll, rr))
                r = rr;
            else
                r = mid;
            return true;
        }
        else if(nums[mid] > target)
            return binarySearch(nums, target, start, mid-1, l, r);
        else
            return binarySearch(nums, target, mid+1, end, l, r);
    }
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        vector<int> vecOut;
        int size = nums.size();
        int l = -1, r = -1;
        binarySearch(nums, target, 0, size-1, l, r);
        vecOut.push_back(l);
        vecOut.push_back(r);
        
        return vecOut;
    }
};

81Search in Rotated Sorted Array II---变种二分查找

问题描述:

Suppose an array sorted in ascending order 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).

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

The array may contain duplicates.

问题解析:

1.  此题依然是在一个旋转数组中,查找一个数字,看是否存在,数组之前是非递减有序的,只不过是经过了旋转。因此,就可以使用二分查找。
2. 使用变种二分查找,需要考虑多种情况,经过旋转之后,因为数组已经不是连续递增数组了。而是一个分半的连续递增,并且可能前半部分每一个数,都大于后半部分每一个数。当然后半部分的数字个数可以为0,也就是不做旋转。
3. 根据二分查找的索引:mid = (start+end)/2,在此题。首先需要判断mid处于前半部分还是后半部分,再根据mid对应值和target值的大小关系来缩小查找范围。代码很清晰,如下所示

代码入下:

class Solution {
public:
    // 利用二分查找来做
    bool BinarySearch(vector<int>& nums, int i, int j, int k)
    {
        if(i>j)
            return false;
        int mid = (i+j)/2;
        // 如果nums[mid]==k,说明已经找到,直接返回true。
        if(nums[mid] == k)
            return true; 
        // 如果nums[mid]大于nums[k],说明mid处于递增段
        if(nums[mid] > nums[i])
        {
            // mid之前都比k小,只能在后面找
            if(nums[mid] < k)   
                return BinarySearch(nums, mid+1, j, k);
            // 此种情况,说明K在前半部分递增段,则只需在前半部分找,就行;因为rotate过的后半部分一定小于nums[i];
            else if(nums[mid] > k && nums[i] <=k)
                return BinarySearch(nums, i, mid-1, k);
            // k在前半部分递增段,但是nums[i]>k,只可能存在于后半部分
            else 
                return BinarySearch(nums, mid+1, j, k);    
        }
        // nums[mid]<nums[i],说明mid在后半部分递增段,且前半部分每一个数都大于等于后半部分每一个数。
        else if(nums[mid] < nums[i])
        {
            // nums[mid]>k,首先mid后是递增,肯定不满足,智能存在于,mid之前的后半部分那几个数
            if(nums[mid] > k)
                return BinarySearch(nums, i, mid-1, k);
            // 如果nums[mid]<k,即可能再在mid后面的递增段,也可能在mid之前的前半部分递增段
            else
                return BinarySearch(nums, i, mid-1, k) || BinarySearch(nums, mid+1, j, k);
        }
        // 如果nums[i] = nums[j] = nums[mid];则只能采用挨个遍历的方式。
        else if(nums[mid] == nums[i] && nums[mid] == nums[j])
            return BinarySearch(nums, i, mid-1, k) || BinarySearch(nums, mid+1, j, k);
        // 如果nums[i]==nums[mid],而且,nums[i] != nums[j],则只可能存在于后半部分
        else
        {
                return BinarySearch(nums, mid+1, j, k);
        }
        
    }
    
    bool search(vector<int>& nums, int target) 
    {
        if(nums.empty())
            return false;
        int size = (int)nums.size();
        int i=0, j=size-1, mid = 0;
        
        return BinarySearch(nums, 0, size-1, target);
    }
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章