Leetcode Difficulty - Find the minimum value I, II in the rotated sorted array (two points + special judgment)

Let's start with finding the minimum value I in the rotated sorted array

Topic:
An array of length n is known, arranged in ascending order in advance, and after 1 to n rotations, the input array is obtained. For example, the original array nums = [0,1,2,4,5,6,7] may be obtained after the change:
if rotated 4 times, you can get [4,5,6,7,0,1,2]
If you rotate 7 times, you can get [0,1,2,4,5,6,7]
Note that the array [a[0], a[1], a[2], …, a[n-1] ] The result of one rotation is the array [a[n-1], a[0], a[1], a[2], …, a[n-2]].
You are given an array nums with mutually different element values, which was originally an array in ascending order and rotated several times as described above. Please find and return the smallest element in the array.
You have to design an algorithm with O(log n) time complexity to solve this problem.

Solution:
This is relatively simple, such as 4 5 6 1 2 3
, then we can find the binary search.
The judgment condition of the binary is whether the value of
l is less than nums[0], set l to 0, r to nums.size() - 1, It is a left-open right-closed interval (excluding the first value).
If nums[mid] is less than nums[0], then r = mid (including mid).
If nums[mid] is greater than nums[0], then l = mid( excluding mid)

Note that if 1 2 3 4 5, the range we are looking for does not include the first value, so 1 will be missed, so the final
result needs to be compared with nums[0] to take the minimum value

code show as below

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

Let's talk about finding the minimum value in the rotation sorted array II

Topic:
An array of length n is known, arranged in ascending order in advance, and after 1 to n rotations, the input array is obtained. For example, the original array nums = [0,1,4,4,5,6,7] may be obtained after the change:
if rotated 4 times, you can get [4,5,6,7,0,1,4]
If you rotate 7 times, you can get [0,1,4,4,5,6,7]
Note that the array [a[0], a[1], a[2], …, a[n-1] ] The result of one rotation is the array [a[n-1], a[0], a[1], a[2], …, a[n-2]].
Given an array nums with possible duplicate element values, it was originally an array in ascending order and rotated several times as above. Please find and return the smallest element in the array.
You have to minimize the number of steps in the whole process as much as possible.

Solution: This
is the first time I saw this kind of algorithm problem that was not considered the worst case, and I thought about the wrong solution.

For this kind of question, dichotomy cannot be used.
If 4 4 4 0 4 4 4 4 4 4 4 4, how do I find this minimum value? No news , so if you consider this special case, the complexity must be O(n), and you need to traverse once


But the meaning of the question is to optimize as much as possible, so how should we consider it?
Use dichotomous points as much as possible, and make special judgments for special cases
. For example, in the previous question

if(nums[mid] > nums[0]) {
    l = mid;
}
else if(nums[mid] < nums[0]) {
    r = mid;
}

It is necessary to make a special judgment on the equal situation, such as 4 xxxx 4 xxxx 4.
We must reduce the range, but we can only reduce the range one by one (otherwise it may be missed).
How to reduce it one by one? You can compare if Boundary on both sides, if it is equal to nums[mid], you can move one to the left or right to shrink the boundary

code show as below

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

Guess you like

Origin blog.csdn.net/m0_52212261/article/details/130137545