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

2023-12-19 06:09:56

?🔥博客主页:?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.打卡

文章来源:https://blog.csdn.net/showy0/article/details/135063360
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。