剑指offer|6.寻找峰值

Posted MicroFrank

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer|6.寻找峰值相关的知识,希望对你有一定的参考价值。

0.寻找峰值

关键点:

  • 返回任意一个峰值的下标即可
  • nums[-1]=nums[n]=负无穷

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

1.傻瓜编程(纯属玩乐)

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

2.二分

看到题目要求的时间复杂度是o(logN),优先考虑二分查找,但是二分查找的前提似乎要是有序的,其实通过这题我们也能发现,使用二分法不一定要求有序只要求可以确定答案一定会出现在其中一边即可

int findPeakElement(int* nums, int numsSize)
    int left=0,right=numsSize-1;
    while(left<right)//
    
        int mid=left+(right-left)/2;
        if(nums[mid+1]>=nums[mid])
        
            left=mid+1;//
        
        else if(nums[mid+1]<nums[mid])
        
            right=mid;//
        
    
    return left;

关键点:

  • 因为mid=(left+right)/2这整数除法的特性,向下取整,只要数组元素个数大于等于2,mid+1下标一定存在(当数组元素等于1的时候,left==right,不会进该循环) , 而mid-1下标不一定存在,mid-1>=0减少边界讨论的情况
  • 注意[left,right] 的范围就是答案所在的区域范围
  • 最后left==right时定位到峰值的位置

LeetCode 字符串的排列全排列问题(剑指offer38)

func permutation(s string) []string {
    //思路:使用寻找下一个增长序列(同官方解题)
    //步骤:1.升序排序 2.依次使用寻找下一个序列查找下一个符合条件的序列 3.返回结果
    bs := []rune(s)
    l := len(bs)
    if l == 0 || l > 8 {
        //panic("参数长度异常")
        return []string{}
    }

    sort.Slice(bs, func (a, b int) bool {
        return bs[a] < bs[b]
    })

    list := make([]string, 0, l)
    for {
        list = append(list, string(bs))
        if !nextPermutation(bs) {
            break
        }
    }
    return list
}

func nextPermutation(bs []rune) bool {
    l := len(bs)
    //左边起始查找位,按照之前置换原则,只有右数比左数大才能有下一个更大序列
    lIdx := l - 2
    for lIdx >= 0 && bs[lIdx] >= bs[lIdx+1] {
        lIdx--
    }
    if (lIdx < 0) {
        return false
    }
    //从最右边开始找,第一个比lIdx大的数即为,最小的大值
    rIdx := l - 1
    for rIdx >= 0 && bs[lIdx] >= bs[rIdx] {
        rIdx--
    }
    bs[lIdx], bs[rIdx] = bs[rIdx], bs[lIdx]
    //按照前面的置换原则,将后面的序列,反转即为新的升序[)
    reverse(bs[lIdx+1:])
    return true
}

func reverse(list []rune) {
    for i, l := 0, len(list); i < l/2; i++ {
        list[i], list[l-1-i] = list[l-1-i], list[i]
    }
}

以上是关于剑指offer|6.寻找峰值的主要内容,如果未能解决你的问题,请参考以下文章

算法系列——寻找旋转排序数组中的最小值(剑指offer)

算法系列——寻找旋转排序数组中的最小值(剑指offer)

算法---- Leetcode剑指offer-Java版题解

算法---- Leetcode剑指offer-Java版题解

⭐算法入门⭐《堆》简单01 —— LeetCode 剑指 Offer 40. 最小的k个数

LeetCode 剑指 Offer 37. 序列化二叉树