c++_leetcode_寻找峰值

C++寻找峰值元素:暴力解法与max_element函数的应用
本文介绍了如何在C++中寻找数组中的峰值元素,包括暴力解法的实现过程、官方提供的解决方案(使用`max_element`函数),并对比了两种方法的优缺点和适用场景。

目录

一、寻找峰值的示例

二、官方实现代码及解释

1、官方测试结果:

2、代码解释:

3、解题思路:

三、我的暴力解决

1、测试一:

2、测试二:

3、最终“暴力求解”代码:

4、官网提交测试通过:

 5、解题思路:

四、c++函数max_element()解决

1、函数使用介绍:

2、max_element() 峰值寻找完整代码:


一、寻找峰值的示例

示例 1:

输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。

示例 2:

输入:nums = [1,2,1,3,5,6,4]输出:1 或 5 
解释:你的函数可以返回索引 1,其峰值元素为 2;
     或者返回索引 5, 其峰值元素为 6。

提示:

  • 1 <= nums.length <= 1000
  • -231 <= nums[i] <= 231 - 1
  • 对于所有有效的 i 都有 nums[i] != nums[i + 1]

二、官方实现代码及解释

1、官方测试结果:

2、代码解释:

class Solution {
public:
    int findPeakElement(vector<int>& nums) {


        //1、准备工作:获得nums、生成随机索引值

        //随机索引值在一定概率上可以快速得到峰值,最好情况是刚好随机到峰值数的索引,最差情况是刚好随机到距离峰值最远的元素
        int n = nums.size();  //得到nums数据长度
        int idx = rand() % n;  //随机生成0~n-1的索引idx值


         //2、设计函数get,输入i,得到数组对(0/1, nums[i])

        // 辅助函数,输入下标 i,返回一个二元组 (0/1, nums[i])
        // 方便处理 nums[-1] 以及 nums[n] 的边界情况

        auto get  = [&](int i)->pair<int,int>{
            if(i==-1||i==n)
            {
                return{0,0};
            }
            return {1,nums[i]};
        };

详细解释lambda表达式:

  • get是函数名
  • [&]是所有变量以引用捕获的方式传入到表达式中,也就是i传入后可访问、修改
  • (int i)是参数列表,这里参数是整型
  • -> pair<int,int>是返回值类型为pair<int,int>,定义为两个int型的数据对
  • {} 里面是函数体,此处返回(0/1, nums[i]),0是超过边界的数对,1是符合边界0~n-1的所有数对

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

        return idx;

    }
};

这里get获得的是(1,nums(i))的pair数据对,pair的first值都是1,所以大小比较的时候对pair的second值进行大小的比较,这个可以mark一下!

3、解题思路:

(1)当不是峰值时,峰值出现在idx的左边或者右边,索引值idx<idx+1时峰值索引变成idx+1,相反idx<idx-1,峰值索引变为idx-1。

(2)i值大于i+1且i值大于i-1

三、我的暴力解决

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int n=nums.size();
        int idx = 0;
        for(int i = 1;i<n-1;i++)
        {
            if(n==2)
            {
                if(nums[i] > nums[i-1])
                {
                    idx = i;
                    break;
                }
                else if(nums[i] < nums[i-1])
                {
                   idx = i-1;
                    break; 
                }
            }
            if(nums[i] > nums[i+1] && nums[i] > nums[i-1]) {
            idx = i;
            break; }

        }

        return idx;
    }
};

1、测试一:

测试用例失败:nums =[1,2],输出0,期望是1

调试一下发现循环条件"n<n-1",当n=2时,n<1,n从1开始,所以没有进入循环判断"if(n==2)"的条件,测试nums =[1,2]案例失败。

修改while循环条件,得到正确输出:

但是,似乎不行呀,执行nums=[1,2,3,4]的时候,没有峰值,所以出错

所以,我发现,官方给的答案确实有他的道理!!!这里没考虑峰值为单边的情况,比如只有上坡或者只有下坡,单独“if (nums[i] > nums[i + 1] && nums[i] > nums[i - 1])”就会报以上的错误了。

2、测试二:

考虑新增上下坡的情况判断 

if (i + 1 == n)
        {
            if (nums[i] > nums[i - 1])
            {
                idx = i;
                break;
            }
            if (nums[i] < nums[i - 1])
            {
                break;
            }
        }

Yes,测试下坡vector<int> nums = {4,3,2,1}通过: 测试上坡vector<int> nums = {1,2,3,4}通过:

3、最终“暴力求解”代码:

在vs上测试代码Solution.cpp、Solution.h、 main.cpp

Solution.cpp

#include "Solution.h"

int Solution::findPeakElement(vector<int>& nums)
{
    int n = nums.size();
    int idx = 0;
    for (int i = 1; i < n ; i++)
    {
        if (n == 2)
        {
            if (nums[i] > nums[i - 1])
            {
                idx = i;
                break;
            }
            else if (nums[i] < nums[i - 1])
            {
                idx = i - 1;
                break;
            }
        }
        if (i + 1 == n)
        {
            if (nums[i] > nums[i - 1])
            {
                idx = i;
                break;
            }
            if (nums[i] < nums[i - 1])
            {
                break;
            }
        }
        if (nums[i] > nums[i + 1] && nums[i] > nums[i - 1]) {
            idx = i;
            break;
        }

    }

    return idx;
}


Solution.h

#pragma once
#include<vector>
using namespace std;
class Solution
{
public:
	int findPeakElement(vector<int>& nums);
};

 mian.cpp

#include<iostream>
using namespace std;
#include"Solution.h"

int main()
{
    vector<int> nums = {4,3,2,1};
    
    Solution Func;
    int index = Func.findPeakElement(nums);

    cout << index << endl;
}

4、官网提交测试通过:

 5、解题思路:

  • 首先想到nums的峰值元素满足条件1:if(nums[i]>nums[i+1]&&nums[i]<nums[i-1]);
  • 提交1后,nums=[1]只有一个元素时,idx应该返回0;所以idx初始值为0;
  • 提交2后,nums=[1,2]只有两个元素时,idx应该等于较大元素,增加两个元素时条件2:if(n==2)时idx=较大值索引;
  • 提交3后,只有上下坡报错,新增条件3:nums=[1,2,3,4]上坡时,idx应该等于最后一个元素的索引;下坡nums=[4,3,2,1]时,idx应该等于最后一个元素的索引;
  • 注意for循环范围for (int i = 1; i < n ; i++)。

四、c++函数max_element()解决

我真的栓Q了,原来函数解决这么简单哦! 

1、函数使用介绍:

max_element()min_element()分别用来求vector容器的最大元素和最小元素的位置

1)vector容器
vector<int> n;
int maxPosition = max_element(n.begin(),n.end()) - n.begin(); //最大值下标
int minPosition = min_element(n.begin(),n.end()) - n.begin();//最小值下标

2)普通数组
int a[]={1,2,3,4};
int maxPosition = max_element(a,a+4) - a; //最大值下标
int minPosition = min_element(a,a+4) - a;//最小值下标

3)最大值最小值
int maxValue1 = *max_element(nums.begin(), nums.end()); //vector最大值
int minValue1 = *min_element(nums.begin(), nums.end());//vector最小值
int maxValue2 = *max_element(a, a + 4); //a[]最大值
int minValue2 = *min_element(a, a + 4);//a[]最小值

2、max_element() 峰值寻找完整代码:

#include<iostream>
using namespace std;
#include <algorithm>

int main()
{
    vector<int> nums = {4,3,2,1};

    int index = max_element(nums.begin(), nums.end()) - nums.begin(); //最大值下标
    cout <<"vector下最大值下标:" << index << endl;

    int a[] = { 4,3,2,1 };
    int maxIdx = max_element(a, a + 4) - a;
    cout << "a[]   下最大值下标:"  << maxIdx << endl;

    int maxValue1 = *max_element(nums.begin(), nums.end()); //最大值
    int minValue1 = *min_element(nums.begin(), nums.end());//最小值
    int maxValue2 = *max_element(a, a + 4); //最大值
    int minValue2 = *min_element(a, a + 4);//最小值

    cout << "vector下的max值:" << maxValue1 << "  min值:" << minValue1 << endl;
    cout << "a[]   下的max值:" << maxValue1 << "  min值:" << minValue2 << endl;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值