数组中的局部最小值

题意

给定一个数组 arr ,其中任意相邻的数均不相等,返回数组中任意一个局部最小值。
局部最小值定义:一个数小于左边邻居且小于右边邻居,若只有左边邻居或右边邻居,
只需要满足小于左边邻居或右边邻居即可。

思路

利用二分查找,通常二分查找应用于有序数组,这里尝试应用在无序数组中。

  • 假设数组中前两个元素arr[0]、arr[1],满足arr[0] < arr[1],则可直接返回arr[0];
  • 假设数组中后两个元素arr[n-1]、arr[n-2],满足arr[n-1] < arr[n-2],则可直接返回arr[n-1];
  • 若不满足前两个条件,则arr[0]>arr[1],这一段单调递减;arr[n-1] > arr[n-2],,这一段单调递增;那么必然在arr[0]…arr[n-1]之间存在局部最小值点,自然想到二分查找。
    令 mid = (int) (L + R) / 2,若满足:
    • arr[mid] < arr[mid-1] and arr[mid] < arr[mid+1],则mid 即为要找的值的索引;
    • arr[mid] > arr[mid-1] and arr[mid] < arr[mid+1],则局部最小值必然在[L, mid-1]之间,继续迭代二分查找;
    • arr[mid] < arr[mid-1] and arr[mid] > arr[mid+1],则局部最小值必然在[mid+1, r]之间,继续迭代二分查找;

代码

python

class BinarySearchLocalMin:
    """
    arr 相邻的数不相等,查找arr中任意一个局部最小值的位置:
    局部最小值定义:
    arr小于左边邻居且小于右边邻居,若只有左边邻居或右边邻居,
    只需要满足小于左边邻居或右边邻居即可;
    """
    def solution(self, arr):
        if not arr or len(arr) == 0:
            return -1
        n = len(arr)
        if n == 1:
            return 0
        if arr[0] < arr[1]:
            return 0
        if arr[n-1] < arr[n-2]:
            return n-1

        l, r = 0, n - 1
        # l, r 之间肯定有局部最小
        while l < r - 1:
            mid = int((l+r)/2)
            if arr[mid] < arr[mid-1] and arr[mid] < arr[mid+1]:
                return mid
            else:
                if arr[mid] > arr[mid - 1]:
                    r = mid - 1
                else:
                    l = mid + 1
        return l if arr[l] < arr[r] else r

Java

public class BinarySearchLocalMin {

	// arr 相邻的数不相等!
	public static int oneMinIndex(int[] arr) {
		if (arr == null || arr.length == 0) {
			return -1;
		}
		int N = arr.length;
		if (N == 1) {
			return 0;
		}
		if (arr[0] < arr[1]) {
			return 0;
		}
		if (arr[N - 1] < arr[N - 2]) {
			return N - 1;
		}
		int L = 0;
		int R = N - 1;
		// L...R 肯定有局部最小
		while (L < R - 1) {
			int mid = (L + R) / 2;
			if (arr[mid] < arr[mid - 1] && arr[mid] < arr[mid + 1]) {
				return mid;
			} else {
				if (arr[mid] > arr[mid - 1]) {
					R = mid - 1;
				} else {
					L = mid + 1;
				}
			}
		}
		return arr[L] < arr[R] ? L : R;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NLP_wendi

谢谢您的支持。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值