【每日一题】【12.18】162.寻找峰值

 🔥博客主页: A_SHOWY
🎥系列专栏力扣刷题总结录 数据结构  云计算  数字图像处理  力扣每日一题_

1.题目链接

162. 寻找峰值icon-default.png?t=N7T8https://leetcode.cn/problems/find-peak-element/

2.题目详情 

今天是一道mid题目,关于寻找峰值,它要求时间复杂度为logn,就能大概猜出来这道题目要用二分法,但是如果这道题目用o(n)的方法做也能通过,而且非常简单。 

3.题目分析解答 

方法一:直接找vector容器中的最大值

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
      return max_element(nums.begin(),nums.end()) - nums.begin();
    }
};

 官方题解中用到的*min_element函数,发现这个函数很方便的用于求vector容器中的最小元素。

int maxPosition = max_element(n.begin(),n.end()) - n.begin(); //最大值下标

int minPosition = min_element(n.begin(),n.end()) - n.begin();//最小值下标

方法二:迭代爬坡 

class Solution {
public:
      
    int findPeakElement(vector<int>& nums) {
        int n = nums.size();
        int idx = rand() % n;//找一个0到n-1的随机数
//处理边界情况
      auto get = [&](int i) -> pair<int,int>{
          if(i == -1 || i == n) return {0,0};
          return {1,nums[i]};
      };

        while(!(get(idx - 1) < get(idx) && get(idx) > get(idx + 1)))
        {
            if(get(idx -1) > get(idx)) idx  -= 1;
            else idx += 1;
        }
return idx;
    }
};

1.需要注意的是,先找一个随机数, 

int idx = rand() % n;//找一个0到n-1的随机数

2.注意处理边界情况用这个lambda函数,Lambda 表达式中的 [&] 表示捕获外部所有变量,int i表示接收一个整型参数

3.pair<int,int> 表示了两个 int 类型的值,确实是一个键值对结构。但在这里,Lambda 函数返回的不是键值对,而是一个表示有效性和数组值的两个值的 pair。在 get Lambda 函数中,使用了 pair<int, int> 结构来表示两个含义不同的整数。其中,第一个整数表示索引是否有效(0 表示无效,1 表示有效),第二个整数表示索引位置上的数组值。这个结构在代码中的意图是标记数组索引的有效性,并提供索引位置上的值。

 4.核心思路:

如果nums[i- 1]<nums[i]> nums[i+1],那么位置à就是峰值位置,我们可以直接返回i作为答案;
如果nums[i-1]< nums[i] < nums[i+1],那么位置i处于上坡,我们需要往右走
如果nums[i-1] >nums[i]>nums[i+1],那么位置i处于下坡,我们需要往左走
如果nums[i-1] >nums[i]<nums[i+1],那么位置i位于山谷,两侧都是上坡,我们可以朝任意方向走
 

方法三:改进的二分法

class Solution {
public:
      
    int findPeakElement(vector<int>& nums) {
        int n = nums.size();
//处理边界情况
      auto get = [&](int i) -> pair<int,int>{
          if(i == -1 || i == n) return {0,0};
          return {1,nums[i]};
      };
     int left = 0,right = n - 1,ans = -1;
     while(left <= right)
     {
         int mid = (right + left)/2;
         if(get(mid -1) < get(mid) && get(mid) > get(mid+1))
         {
             ans = mid;
             break;
         }
         else if(get(mid) < get(mid + 1)) left = mid+1;
         else right = mid -1;
     }
    return ans;
    }
};

核心思路:对于当前可行的下标范围[l, r],我们随机一个下标i;
如果下标i是峰值,我们返回i作为答案;
如果nums[i]< numsi+1],那么我们抛弃1,i的范围,在剩余[i+1,r]的范围内继续随机选取下标。
如果nums[i]> nums[i+1],那么我们抛弃[i,r]的范围,在剩余[l,i-1]的范围内继续随机选取下标。

其他的思路和方法二其实是一样的

4.打卡

  • 32
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A_SHOWY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值