【打卡】牛客网:BM21 旋转数组的最小数字

学习资料:

归并排序NlogN和二分法查找logN的区别:

归并排序及二分法_二分法归并-CSDN博客

自己写的:

 用了递归的方法,受“BM19 寻找峰值”的影响,用二分法来查找,复杂度是O(logN)。

查找后本来想恢复旋转矩阵的,但是后来想到,找到高峰元素就已经找到最小值了。

编程细节:递归的left和right的判断很难把握。

注:样例中居然出现了没有旋转的数组。观察了旋转矩阵的特点,第一个元素比最后一个元素大(或者相等),所以判断没有旋转的数组还是比较简单的。

递归对于第一个元素和最后一个元素相等的情况也很好地处理了。

class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param nums int整型vector
     * @return int整型
     */
    int findPeakElement(int left, int right, vector& nums) {
        if (left >= right) // 判断条件很难把握
            return -1;
        int mid = (left + right) / 2;

        // 如果mid的右边是下降的
        if (nums[mid] > nums[mid + 1]) 
            return nums[mid + 1];
        int ans1 = findPeakElement(left, mid, nums);
        if (ans1 != -1) 
            return ans1;
        int ans2 = findPeakElement(mid + 1, right, nums);
        return ans2;
    }
    int minNumberInRotateArray(vector& nums) {
        // write code here
        if(nums[0] < nums[nums.size()-1])  
            return nums[0];
        int ans = findPeakElement(0, nums.size() - 1, nums);
        return ans < nums[0] ? ans : nums[0];
    }
};

考虑不用递归,用while循环的方法。受启发,比较与第一个元素:

但是对于多个重复元素旋转的问题不能解决。

下述代码不能通过。

     int minNumberInRotateArray(vector& nums) {
        // write code here
        if(nums[0] <= nums[nums.size()-1])  
            return nums[0];
        
        int left = 0;
        int right = nums.size()-1;
        int minN = -1;

        while(left <= right){
            int mid = (left + right) / 2;
            if(nums[mid] >= nums[0])
                left = mid + 1;
            else{
                minN = nums[mid]; 
                right = mid -1; 
            }
        }
        return minN;
    }

刷题模板的:

与最右边right进行比较,而不是mid的右边mid+1。

不能与最左边left进行比较,因为在只剩下两个元素的时候,mid恒等于left。

亮点:如果难以判断,则一个一个试:

else if (nums[mid] == nums[right])
        right --;

因为比较的是nums[right](不是“自己写的”里的固定值nums[0]),所以难以判断的话,right缩小范围,而不是left缩小范围。 

综上,一切都非常巧妙。

①与right进行比较 ②是right缩小范围 ③最后返回的结果是left

class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param nums int整型vector
     * @return int整型
     */
    int minNumberInRotateArray(vector& nums) {
        // write code here
        int left = 0;
        int right = nums.size() - 1;

        while (left < right) { // 不是 <=
            int mid = (left + right) / 2;
            // 最小值一定在右边,mid一定不是最小值 
            if (nums[mid] > nums[right])         
                left = mid + 1; 

            // 最小值不确定在哪
            else if (nums[mid] == nums[right])
                right --;  //不是 left ++

            // 最小值一定在左边,mid可能是最小值
            else
                right = mid; 
        }

        return nums[left]; // 不是 return nums[right];
    }
};

你可能感兴趣的:(算法,数据结构,leetcode)