分治3:关于山脉数组的两道题

Posted 纵横千里,捭阖四方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分治3:关于山脉数组的两道题相关的知识,希望对你有一定的参考价值。

在LeetCode中有两道关于山脉的问题LeetCode852和1095。通过这两个题,我可以放心的和你说,LeetCode刷完前1000道就够了,后面1500道基本不用看。

1.LeetCode852. 山脉数组的峰顶索引

这个题的内容表述有点啰嗦,

符合下列属性的数组 arr 称为 山脉数组 :
arr.length >= 3
存在 i(0 < i < arr.length - 1)使得:

  •      arr[0] < arr[1] < ... arr[i-1] < arr[i]
  • arr[i] > arr[i+1] > ... > arr[arr.length - 1]

给你由整数组成的山脉数组 arr ,返回任何满足 arr[0] < arr[1] < ... arr[i - 1] < arr[i] > arr[i + 1] > ... > arr[arr.length - 1] 的下标 i 。

分析

这里的意思其实就是说在数组中的某位位置i开始,从0到i是递增的,从i+1 到数组最后是递减的,让你找到这个最高点。

这个题其实就是前面找最小值的相关过程而已,使用二分法轻松搞定。

记满足题目要求的下标 i为 ans ,我们可以发现:

  • 当i<ans时,arr[i]<arr[i+1]
  • 当i>=ans时,arr[i]>=arr[i+1]

实现过程就是:

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

2.LeetCode1095. 山脉数组中查找目标值

要求就是在上面的基础上:

给你一个 山脉数组 mountainArr,请你返回能够使得 mountainArr.get(index) 等于 target 最小 的下标 index 值。

如果不存在这样的下标 index,就请返回 -1。

示例1:
输入:array = [1,2,3,4,5,3,1], target = 3
输出:2
解释:3 在数组中出现了两次,下标分别为 2 和 5,我们返回最小的下标 2。

做了上面的题,这个题的解答就三句话:

  1. 先使用二分法找到数组的峰值。
  2. 在峰值左边使用二分法寻找目标值。
  3. 如果峰值左边没有目标值,那么使用二分法在峰值右边寻找目标值。代码就是
    class Solution {
        public int findInMountainArray(int target, MountainArray mountainArr) {
            int l = 0, r = mountainArr.length() - 1;
            while (l < r) {
                int mid = (l + r) / 2;
                if (mountainArr.get(mid) < mountainArr.get(mid + 1)) {
                    l = mid + 1;
                } else {
                    r = mid;
                }
            }
            int peak = l;
            int index = binarySearch(mountainArr, target, 0, peak, true);
            if (index != -1) {
                return index;
            }
            return binarySearch(mountainArr, target, peak + 1, mountainArr.length() - 1, false);
        }
    
        public int binarySearch(MountainArray mountainArr, int target, int l, int r, boolean flag) {
            if (!flag) {
                target *= -1;
            }
            while (l <= r) {
                int mid = (l + r) / 2;
                int cur = mountainArr.get(mid) * (flag ? 1 : -1);
                if (cur == target) {
                    return mid;
                } else if (cur < target) {
                    l = mid + 1;
                } else {
                    r = mid - 1;
                }
            }
            return -1;
        }
    }

​ 

以上是关于分治3:关于山脉数组的两道题的主要内容,如果未能解决你的问题,请参考以下文章

关于字符串的两道题

关于Python字典的两道题目

数组2:合并有序数组的两道题

小测(noip2005的两道题) 2017.3.3

刷了两道题

php封装协议的两道题