二分查找在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);
    }
};


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