[Leetcode] Dichotomy title record: leetcode33 and leetcode153

One, in front

I recently prepared for an interview, and the algorithmic questions passed the dichotomy. Therefore, several classic dichotomy questions on leetcode have been brushed. Here are two dichotomy questions of medium difficulty.

Two, leetcode33

(1) Title description

Assume that the array sorted in ascending order is rotated at a point unknown in advance.

(For example, the array [0,1,2,4,5,6,7] may become [4,5,6,7,0,1,2]).

Search for a given target value, if the target value exists in the array, return its index, otherwise return -1.

You can assume that there are no duplicate elements in the array.

The time complexity of your algorithm must be O(log n) level.

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

(2) Code

class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
    
        int begin=0;
        int end=nums.size()-1;
        int index;
        while(begin<=end)
        {
    
    
            index=(begin+end)/2;
            if(nums[index]==target)
                return index;
            else if(nums[end]>=nums[index])
            {
    
    
                if(target>=nums[index]&&target<=nums[end])
                    begin=index+1;
                else
                    end=index-1;
            }
            else
            {
    
    
                if(target>=nums[begin]&&target<=nums[index])
                    end=index-1;
                else
                    begin=index+1;
            }
        }
        return -1;
    }
};

(3) Analysis

The key point of this topic is to know that every time the dichotomy, the left and right sides of the dichotomy position (that is, the index in the code above), that is, the data in the [begin, index] and [index, end] parts of the code Among them, one of them must be monotonically increasing. Because of the definition of the rotation array here, this determines this. In this case, every time we are in the while(begin<=end) loop, we can judge whether the increment interval is [begin,index] or [by judging the size of the two data nums[end] and nums[index] index,end]. If the increment interval is [begin, index], by judging whether the target is greater than nums[begin] and less than nums[index], you can know whether the target is in the interval of [begin, index]. If it is in the interval of [begin, index], use it as the next dichotomy interval, otherwise, use another [index, end] as the next dichotomy interval.
The point is to think clearly, every time a dichotomy, there must be an increase in the left and right intervals.

Three, leetcode153

(1) Title description

Assume that the array sorted in ascending order is rotated at a point unknown in advance.

(For example, the array [0,1,2,4,5,6,7] may become [4,5,6,7,0,1,2]).

Please find the smallest element.

You can assume that there are no duplicate elements in the array.

Example 1:

Input: [3,4,5,1,2]
Output: 1

Example 2:

Input: [4,5,6,7,0,1,2]
Output: 0

(2) Code

My code:

class Solution {
    
    
public:
    int findMin(vector<int>& nums) {
    
    
        int minimun=10000;
        int left=0;
        int right=nums.size()-1;
        int center;
        if(nums.size()==1)
        return nums[0];
        if(nums[nums.size()-1]>nums[0])
        return nums[0];
        // if(nums[nums.size()-1]<nums[nums.size()-2])
        // return nums[nums.size()-1];
        while(left<=right)
        {
    
    
            center=(left+right)/2;
            if(center!=0&&center!=(nums.size()-1))
            {
    
    
                if(nums[center]<nums[center-1]&&nums[center]<nums[center+1])
                {
    
    
                    return nums[center];
                }
            }
            if(right>=(center+1)&&nums[right]>=nums[center+1])
            {
    
    
                if((center+1)>0&&(center+1)<(nums.size()-1))
                {
    
    
                    if(nums[center+1]<nums[center]&&nums[center+1]<nums[center+2])
                    {
    
    
                        return nums[++center];
                    }
                }
                right=center-1;
            }
            if((center-1)>=left&&nums[center-1]>=nums[left])
            {
    
    
                if((center-1)>0&&(center-1)<(nums.size()-1))
                {
    
    
                    if(nums[center-1]<nums[center-2]&&nums[center-1]<nums[center])
                    {
    
    
                        return nums[--center];
                    }
                }
                left=center+1;
            }
        }
        return -1;
    }
};

The more concise code on the Internet:

class Solution {
    
    
public:
    int findMin(vector<int>& nums) {
    
    
        int left=0;
        int right=nums.size()-1;
        int center;
        if(nums.size()==1)
        return nums[0];
        if(nums[nums.size()-1]>nums[0])
        return nums[0];
        while(left<right)
        {
    
    
            center=(left+right)/2;
            if(nums[center]>nums[left])
            left=center;
            else
            right=center;
        }
        return min(nums[left],nums[left+1]);
    }
};

(3) Analysis

On this topic, my code is too complicated, mainly because when I wrote it myself, I thought it was too complicated. Considering many situations, the code became more and more complicated. In fact, this problem is similar to the problem-solving idea of ​​leetcode33 above, and it is also necessary to use the characteristics of the rotating array. There must be an increment in the left and right intervals. Then every time we can find the incrementing interval first, after finding it, our smallest element is definitely not in this incrementing interval, but there is a very important point of this idea, it is also possible to know the data of the center position obtained every time. Is the smallest element we want to find. So after we determine the increment interval, we must take the center position into consideration when determining the interval of the next cycle. That is, the operation at this time is left=center or right=center instead of left=center+1 or right=center-1.

Guess you like

Origin blog.csdn.net/qq_38391210/article/details/108150126