Leetcode. 在数组中找到一个局部最小的位置

问题

定义局部最小的概念.

  • arr长度为1时, arr[0]是局部最小
  • arr长度为N(N > 1)时, 如果arr[0] < arr[1], 那么arr[0]是局部最小
  • 如果arr[N-1] < arr[N-2]时, 那么arr[N-1]是局部最小
  • 如果0 < i< N-1, 既有 arr[i] < arr[i – 1], 又有arr[i] < arr[i + 1], 那么arr[i]是局部最小
    给定一个无序数组arr, 已知arr中任意两个相邻的数都不相等. 写一个函数, 只需返回arr中任意一个局部最小出现的位置即可.

分析

顺序遍历是最直接的方法, 时间复杂度是O(n).
下面介绍一种时间复杂度O(logN)的方法.
基本思想: 二分查找.

  1. 如果数组长度为0, 返回 -1
  2. 如果数组长度为1, 返回0
  3. 如果arr[0] < arr[1], 返回0
  4. 如果arr[size – 1] < arr[size – 2], 返回size – 1
  5. 从arr[1]到arr[size – 2]开始二分查找
  6. left = 1, right = size – 2
  7. mid = left + (right – left) / 2
  8. 如果arr[mid] > arr[mid – 1], 那么在mid左侧,必然存在局部最小位置, 令righ = mid – 1. 继续二分查找
    举个栗子: 对于数组 {x, 2, 3, 5, 6}, mid = 2, arr[2] > arr[1], 如果处于位置0的x值小于2, 那么满足第三步的条件, 所以x值一定大于2, 位置1即是满足条件的位置.
  9. 同样可以分析, 如果arr[mid] > arr[mid + 1], 那么在mid右侧, 必然存在局部最小位置, 令left = mid + 1. 继续二分查找.
  10. 如果不满足5.3, 5.4, 那么mid所在位置即是满足条件的位置.

实现

class Solution                                                                                                                                        
{
public:
    int partialMinimum(const std::vector<int>& nums)
    {
        int size = nums.size();
        if (size == 0)
        {
            return -1;
        }
        if (size == 1 || nums[0] < nums[1])
        {
            return 0;
        }
        if (nums[size - 1] < nums[size - 2])
        {
            return size - 1;
        }
        int left = 1;
        int right = size - 2;
        int result = -1;
        while (left <= right)
        {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[mid - 1])
            {   
                right = mid - 1;
            }   
            else if (nums[mid] > nums[mid + 1]) 
            {   
                left = mid + 1;
            }   
            else
            {   
                result = mid;
                break;
            }   
        }   
        return result;
    }
};
    原文作者:周肃
    原文地址: https://www.jianshu.com/p/bc8ca0c50ba3
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞