leetcode-162-寻找峰值(find peak element)-java

题目及测试

package pid162;
/*寻找峰值

峰值元素是指其值大于左右相邻值的元素。

给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。

数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞。

示例 1:

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

示例 2:

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

说明:

你的解法应该是 O(logN) 时间复杂度的。

*/


public class main {
	
	public static void main(String[] args) {
		int[][] testTable = {{1,2,3,1},{1,2,1,3,5,6,4},{1,2},{3,2,1,5,6,4}};
		for (int[] ito : testTable) {
			test(ito);
		}
	}
		 
	private static void test(int[] ito) {
		Solution solution = new Solution();
		int rtn;
		long begin = System.currentTimeMillis();
		for (int i = 0; i < ito.length; i++) {
		    System.out.print(ito[i]+" ");		    
		}
		System.out.println();
		//开始时打印数组
		
		rtn = solution.findPeakElement(ito);//执行程序
		long end = System.currentTimeMillis();	
		
		//System.out.println(ito + ": rtn=" + rtn);
		System.out.println(": rtn=" +rtn);
		
		
		System.out.println();
		System.out.println("耗时:" + (end - begin) + "ms");
		System.out.println("-------------------");
	}

}

解法1(成功,3ms,极快)

直接顺序查找,看now>prev&&now>next即可

package pid162;

import java.util.Arrays;

import javax.naming.InitialContext;

public class Solution {
public int findPeakElement(int[] nums) {
    int length=nums.length;
    if(length==1){
    	return 0;
    }
    int prev=nums[0];
    int now=nums[1];   
    int next;    
    int index=0;
    for(int i=1;i<length-1;i++){
    	next=nums[i+1];
    	if(now>prev&&now>next){
    		index=i;    		
    		break;
    	}
    	prev=now;
    	now=next;
    }
    if(nums[0]>nums[1]){
    	index=0;
    }
    if(nums[length-1]>nums[length-2]){
    	index=length-1;
    }
	
	
	return index;
    }
}

解法2(别人的)

在简单的二分查找中,我们处理的是一个有序数列,并通过在每一步减少搜索空间来找到所需要的数字。在本例中,我们对二分查找进行一点修改。首先从数组 nums 中找到中间的元素 mid。若该元素恰好位于降序序列或者一个局部下降坡度中(通过将 nums[i] 与右侧比较判断),则说明峰值会在本元素的左边。于是,我们将搜索空间缩小为 mid的左边(包括其本身),并在左侧子数组上重复上述过程。

若该元素恰好位于升序序列或者一个局部上升坡度中(通过将 nums[i]与右侧比较判断),则说明峰值会在本元素的右边。于是,我们将搜索空间缩小为 mid的右边,并在右侧子数组上重复上述过程。

就这样,我们不断地缩小搜索空间,直到搜索空间中只有一个元素,该元素即为峰值元素。

最左端和最右端元素均无限小,中间元素比两侧都要大,那么本题中一定存在一个峰元素。所以不管中间有多少波峰,只要找到峰元素,我们只需找到刚刚开始下降而未下降的位置。采用二分查找,查出这样一个位置即可,我们知道二分查找要比较的是 target 元素,本题的 target 元素是 mid 的后一个元素,即 nums[mid] 与 nums[mid+1] 进行比较:
 

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

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值