算法整理-二分查找列表最大值

需求描述

已知一个列表是先增后减的半有序列表,现在需要找出列表中的最大值,列表长度可能很大,考虑时间复杂度,该算法该如何实现?

实现思路

在不考虑时间复杂的的情况下,可以直接遍历,用max标识来记录最大值,知道找到一个比最大值小的记录,说明列表开始降序,最大值就找到了。
如果考虑到时间复杂度,且是半有序的列表,收到二分查找的启发,可以使用二分查找,每次比较中间项与其相邻元素的大小,判断最大值所处的范围。例如:如果mid>mid-1,说明是增,最大值就在【mid,last】区间里面,否则就是在【first,mid】区间。如果只剩下2-3个元素,就找最大值,如果在当前区间里面first>first+1说明开始降序,最大值就是first。

Java实现代码

public static Integer findMax(List<Integer> list, int first, int last) {
        //只剩下两个元素,或者只剩下三个元素
        if(last==first+1||last==first+2){
            return Collections.max(list.subList(first, last+1));
        }

        //3个以上的元素,并且开始降序了,则直接返回第一个值
        if (list.get(first) > list.get(first + 1)) {
            return list.get(first);
        }

        //否则,折半确定最大值的范围
        int middle = (first + last) / 2;
        System.out.println("middle:"+middle);
        if (list.get(middle) > list.get(middle - 1)) {
            // 升序
            return findMax(list, middle, last);
        }

        return findMax(list, first, middle);
    }tring[] args) {
        Integer [] array1 = {15, 16, 17, 18, 19, 20 };
        Integer [] array2 = { 21, 22,23,24,25, 20, 19, 18, 17, 16,11,10,9 };
        List<Integer> asc = new ArrayList<Integer>();
        asc.addAll(Arrays.asList(array1));
        asc.addAll(Arrays.asList(array2));
        System.out.println(asc);

        System.out.println(findMax(asc,0,asc.size()-1));
    }
}

复杂度分析

每次折半,算法时间复杂度和二分查找时间复杂度一样,是logN,取决于列表的长度。如果在列表特别长的情况下,应该会比直接遍历的N的复杂度低一些。

    原文作者:查找算法
    原文地址: https://blog.csdn.net/wojiushiwo945you/article/details/53037487
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞