zoukankan      html  css  js  c++  java
  • 【LeetCode-查找】寻找旋转排序数组中的最小值 II

    题目描述

    假设按照升序排序的数组在预先未知的某个点上进行了旋转。
    ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
    请找出其中最小的元素。
    注意数组中可能存在重复的元素。
    示例:

    输入: [1,3,5]
    输出: 1
    
    输入: [2,2,2,0,1]
    输出: 0
    

    题目链接: https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/
    做这题之前可以先做一下寻找旋转排序数组中的最小值

    思路1

    寻找旋转排序数组中的最小值思路类似,只是这题的数组中可能会存在重复的元素。在寻找旋转排序数组中的最小值中,我们通过nums[left]、nums[right]和nums[mid]之间的关系来判断nums[mid]位于哪个数组当中,从而缩小查找的范围。但是这题中由于重复元素的存在,可能会出现nums[left]==nums[mid]==num[right]的情况,这时候无法判断nums[mid]位于哪个数组,也无法缩小查找范围。当遇到三者相等的情况时,可以在[left, right]范围内遍历查找最小值。代码和寻找旋转排序数组中的最小值基本一样,只多加了判断三者相等的情况以及对应的处理。代码如下:

    class Solution {
    public:
        int findMin(vector<int>& nums) {
            if(nums.size()==1) return nums[0];  // 注意长度为1的情况
            
            int left = 0, right = nums.size()-1;
            if(nums[right]>nums[left]) return nums[left];
            while(left<=right){
                int mid = left+(right-left)/2;
                if(nums[left]==nums[mid] && nums[mid]==nums[right]){    // 三者相等,遍历查找
                    int minVal = 0x7fffffff;
                    for(int i=left; i<=right; i++){
                        minVal = min(nums[i], minVal);
                    }
                    return minVal;
                }
                
                if(nums[mid]>nums[mid+1]) return nums[mid+1];
                if(nums[mid]<nums[mid-1]) return nums[mid];
    
                if(nums[left]<=nums[mid]) left = mid+1; // 注意是<=
                else if(nums[right]>=nums[mid]) right = mid-1;  // 注意是>=
            }
            return -1;  // 返回多少无关紧要,因为不会跑到这一步
        }
    };
    
    • 时间复杂度:O(n+logn)
    • 空间复杂度:O(1)

    思路2

    看了题解发现有更简洁的写法。只将nums[right]和nums[mid]作比较:

    • 如果nums[mid]>nums[right],则说明nums[mid]在左边的数组当中,最小值在mid右边,所以left = mid+1;
    • 如果nums[mid]<nums[right],则说明nums[mid]在右边的数组当中,最小值的mid左边,所以right=mid;
    • 如果nums[mid]==nums[right],将right--;

    代码如下:

    class Solution {
    public:
        int findMin(vector<int>& nums) {
            if(nums.size()==1) return nums[0];  // 注意长度为1的情况
            
            int left = 0, right = nums.size()-1;
            //if(nums[right]>nums[left]) return nums[left];
            while(left<=right){    // 可以写成<
                int mid = left+(right-left)/2;
    
                if(nums[mid]>nums[right]) left=mid+1;
                else if(nums[mid]<nums[right]) right = mid;
                else right--;
            }
            return nums[left]; 
        }
    };
    
    • 时间复杂度:O(logn)
    • 空间复杂度:O(1)

    这种解法就是寻找旋转排序数组中的最小值的解法。

  • 相关阅读:
    PHP脚本如何正确启用sg11安全组件?
    android修改系统时系统黑屏时不进入休眠状态
    计算机自考视频汇总【福利资料】[转]
    解决MySql报错:1130
    “领导想提拔你,看的从不是努力
    interTbale ___AlterTable
    MySQL数据库管理系统概述
    《分布式任务调度平台XXL-JOB》
    mysql 在线文档
    Oracle19c 数据库在线文档
  • 原文地址:https://www.cnblogs.com/flix/p/12805517.html
Copyright © 2011-2022 走看看