面试题:查找先非严格递增后非严格递减的数组中的最大值 java

一道面试题要求在非严格递增后非严格递减的整数数组中找到最大值。传统的遍历方法虽然简单但效率较低。通过二分查找,利用数组特性,可以在log(N)的时间复杂度内找到答案。Java实现中,需注意找到相等数字的左右边界,以确定最大值所在位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是一道本人面试时手撕算法环节的真题。

给定一个整数数组,这个数组中的数字有这样一个规律:前面部分非严格递增,后面部分非严格递减,写出找到其中最大值的算法。

说明:所谓非严格递增是指arr[i]<=arr[i+1],相应的非严格递减是指arr[i]<=arr[i+1]。例如下面的这些例子:

int[] arr1 = new int[]{1, 2, 3, 4, 5, 6, 7, 7, 5, 5, 5, 5, 4, 4, 4, 4, 2, 2, 2, 1, 1};
int[] arr2 = new int[]{7, 7, 7, 5, 5, 5, 5, 4, 4, 4, 4, 2, 2, 2, 1, 1};
int[] arr3 = new int[]{1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 7, 7, 7};
int[] arr4 = new int[]{7, 7, 7, 7, 7, 7};

题解:
要求数组中的最大值,最简单的办法就是遍历,从头开始,直至出现arr[i+1]<arr[i],那么此时的arr[i]当然就是数组中的最大值。但是面试的时候面试官肯定不想让你这样做,因为这个时间复杂度为O(N)。

由于前半部分递增,后半部分递减,我们可以想到二分查找,因为二分查找算法用来查找有序或者部分有序的数组中的元素时间复杂度为log(N)。

下面是java代码,其中比较曲折的一点在于,每一次找到中间的元素之后都需要通过while循环来找到这一段相等数字的左右边界。例如:2,2,3,3,3,4,如果mid位置的值是中间的那个3,那么就需要找到左右两边与他不相等的值2和4,这样就能够判断出来,此时的mid位于爬坡的位置,需要将下边界指向4的位置。

代码中还有详细的注释,保证理解。

public class FindMaxNum {
    /**
     * 查找先非严格递增后非严格递减的数组中的最大值
     * 利用二分查找法
     */
    private static int findMaxNum(int[] arr) {
        int index = 0;
        int length = arr.length;
        for (int i = 0, j = length - 1; i < j; ) {//i是下边界,j是上边界
            int mid = (i + j) / 2;

            //下面两个while循环找到左右不相等的边界或者数组的边界
            int left = mid - 1;
            while (arr[left] == arr[mid] && left > 0) {
                left--;
            }
            int right = mid + 1;
            while (arr[right] == arr[mid] && right < length - 1) {
                right++;
            }

            //通过判断当前mid坐在位置,上坡,下坡或者坡顶来找到最大值
            if (arr[mid] > arr[left] && arr[mid] < arr[right]) {
                i = right;
            } else if (arr[mid] < arr[left] && arr[mid] > arr[right]) {
                j = left;
            } else if (arr[mid] >= arr[left] && arr[mid] >= arr[right]) {//这个地方需要以等号作为条件,因为可能最大值在边界处
                index = mid;
                break;
            }
        }
        return arr[index];
    }

    public static void main(String[] args) {
        int[] arr1 = new int[]{1, 2, 3, 4, 5, 6, 7, 7, 5, 5, 5, 5, 4, 4, 4, 4, 2, 2, 2, 1, 1};
        int[] arr2 = new int[]{7, 7, 7, 5, 5, 5, 5, 4, 4, 4, 4, 2, 2, 2, 1, 1};
        int[] arr3 = new int[]{1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 7, 7, 7};
        int[] arr4 = new int[]{7, 7, 7, 7, 7, 7};
        int maxNum = findMaxNum(arr1);
        System.out.println(maxNum);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值