• 162. Find Peak Element


    题目:

    A peak element is an element that is greater than its neighbors.

    Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.

    The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

    You may imagine that num[-1] = num[n] = -∞.

    For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

    链接: http://leetcode.com/problems/find-peak-element/

    题解:

    找1D-Peak,正好是MIT 6.006第一课的第一个问题。使用Binary Search,当nums[mid] < nums[mid + 1],nums[mid + 1]可能为peak,设置lo = mid + 1, else设置hi = mid。当lo == hi时,找到peak。 

    Time Complexity - O(logn), Space Compleixty - O(1)。

    public class Solution {
        public int findPeakElement(int[] nums) {            //MIT 6.006 Introduction to Algorithms
            if(nums == null || nums.length == 0)            // watch the 2d version
                return 0;
            int lo = 0, hi = nums.length - 1;
            
            while(lo <= hi) {
                if(lo == hi)
                    return lo;
                int mid = lo + (hi - lo) / 2;
                if(nums[mid] < nums[mid + 1])
                    lo = mid + 1;
                else
                    hi = mid;
            }
            
            return -1;
        }
    }

    Python:

    class Solution(object):
        def findPeakElement(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            if not nums:
                return -1
            lo = 0
            hi = len(nums) - 1
            
            while lo <= hi:
                if lo == hi:
                    return lo
                mid = lo + (hi - lo) / 2
                if nums[mid] < nums[mid + 1]:
                    lo = mid + 1
                else:
                    hi = mid
                    
            return -1
            

    Follow up是找2D-Peak,这时候要用Divide-and-Conquer,在一个类似window的方框(first,mid,last row and column)里遍历所有元素。找不到的话,在window所有元素中的最大元素的neighbor里,找到一个比这个元素大的neighbor,然后在这个neighbor所在的 (n/2 x n/2)的小window里找,这次查找包括之前的边框,之后recursively。 详细的方法还要继续看mit的slides,Time Complexity是O(n)。

    二刷:

    此题在Microsoft Excel组onsite时第一轮第一题考到了,还问到了follow up。发现自己了解得并不是很深刻。下面记录一下重新思考后的写法,写得比较sloppy。 三刷的时候要进行化简。

    题目给定了一个数组,要求在数组中找到一个peak。以前在Youtube MIT的视频里看到过,所以知道有几种方法可以做到。我们不考虑题目给定的nums[i] != nums[i - 1]的条件,对于general case来说, 假如index i在的nums[i]是一个peak,那么一定有 nums[i] >= nums[i - 1] 并且nums[i] >= nums[i + 1]。 

    1. 顺序查找,从1到 len - 2里顺序比较nums[i] >= nums[i - 1] && nums[i] >= nums[i + 1]
    2. 找到global最大值,global最大值也是一个peak
    3. binary search。我们每次查找一个中间mid, 将mid和它左右两边的元素进行比较,假如mid是peak,那么我们直接返回。否则假如nums[mid] < nums[mid - 1],从mid向队首肯定有一个上升序列,我们在左半边继续查找, 否则nums[mid] < nums[mid + 1], 从mid向队尾肯定有一个上升序列,我们在右半边继续查找。最后return lo或者hi都可以。 在查找之前也要处理一下边界问题。边界问题的精简还需要好好思考,再多写一写。最后也要考虑一些test case,自己测试一下。

    Java:

    Binary Search:

    Time Complexity - O(logn), Space Compleixty - O(1)。

    public class Solution {
        public int findPeakElement(int[] nums) {
            if (nums == null || nums.length < 2) {
                return 0;
            }
            if (nums[0] >= nums[1]) {
                return 0;
            }
            int len = nums.length;
            if (nums[len - 1] >= nums[len - 2]) {
                return len - 1;
            }
            int lo = 1, hi = len - 2;
            while (lo < hi) {
                int mid = lo + (hi - lo) / 2;
                if (nums[mid] >= nums[mid - 1] && nums[mid] >= nums[mid + 1]) {
                    return mid;
                } else if (nums[mid] < nums[mid - 1]) {
                    hi = mid - 1;
                } else {
                    lo = mid + 1;
                }
            }
            return lo;
        }
    }

    Update:

    上面的代码过长,还是可以简化到一刷的代码。

    public class Solution {
        public int findPeakElement(int[] nums) {
            if (nums == null || nums.length < 2) return 0;
            int lo = 0, hi = nums.length - 1;
            
            while (lo <= hi) {
                if (lo == hi) return lo;
                int mid = lo + (hi - lo) / 2;
                if (nums[mid] < nums[mid + 1]) {
                    lo = mid + 1;
                } else {
                    hi = mid;
                }
            }
            return lo;
        }
    }

    Test Case:

    1.  [1, 3, 4, 2, 4, 3, 1]

    Reference:

    http://stellar.mit.edu/S/course/6/fa13/6.006/materials.html

    https://docs.python.org/2/tutorial/

    http://stellar.mit.edu/S/course/6/fa13/6.006/courseMaterial/topics/topic6/lectureNotes/L01_-_Peak_Finding/L01_-_Peak_Finding.pdf

    http://stellar.mit.edu/S/course/6/fa13/6.006/courseMaterial/topics/topic4/lectureNotes/rec01_intro/rec01_intro.pdf

  • 相关阅读:
    App开发Native.js入门指南
    C# Dapper 基本使用 增删改查事务等
    特殊字符码
    assert
    俩个高斯分布之间的KL散度
    np.random.normal(loc=0,scale=1e-2,size=shape)
    解决Github加载ipynb文件缓慢/失败
    画出8个高斯分布散点图
    解决tensorflow报错ValueError: Variable conv1/weights already exists, disallowed.原因:第二次使用的是第一次的就的变量
    互信息
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4489719.html
Copyright © 2020-2023  润新知