算法题 输出第n大的数

前言

给定一个数组以及一个数字n,输出数组中第n大的数,例如数组

array = {1,4,6,5,4,7,8,9,10} 

n = 5

那么输出的数字是 6。

本文会提供几种不同的写法,从效率上我们一起来看看

正文

第一种

首先我们想到对数组进行排序,利用Arrays.sort()方法,然后从后往前数出第n大数,代码如下

/**
     * 给定一个数组和n,输出第n大数
     * 不存在则返回0
     *
     * @param arr 数组
     * @return 第n大的数
     */
    public static int findNMaxNumberVersion1(int[] arr, int n) {
        if (arr == null || arr.length == 0 || n > arr.length){
            return 0;
        }
        Arrays.sort(arr);
        return arr[arr.length - n];
    }

那么我们来思考,这种方法是最优的吗?

肯定不是最优的,我们只是想找出第n大数,上述解法将所有数都排序了一遍,必然多出来很多无效的操作,但是这种写法是最简洁的。

第二种

/**
     * 给定一个数组和n,输出第n大数
     * 不存在则返回0
     *
     * @param arr 数组
     * @return 第n大的数
     */
    public static int findNMaxNumberVersion2(int[] arr, int n) {
        if (arr == null || arr.length == 0 || n > arr.length){
            return 0;
        }
       int count = 0;
        for (int i = 0;i < arr.length;i++){
           int temp =  arr[0];
           int m = 0;
           int j = 1;
           while (j < arr.length){
               if (arr[j] > temp){
                   temp = arr[j];
                   m = j;
               }
               j++;
           }
           arr[m] = 0;
           count++;
           if (count == n){
               return temp;
           }
        }
        return 0;
    }

这种写法比第一种效率高出不少,他不会将所有的数都排序一遍,而只是将最大的n - 1个数重置为0,返回第n个数。对剩下的数,不会进行重复无效的计算。那么我们来思考,这种解法有没有优化的空间呢?显然是可以的。我们发现上述的代码,将最大的数都重置为0,但是下次遍历的时候,还会遍历到这些重置的数据,假如整个数组有1万个元素,我们要找到第5千个大数,那么遍历数组的大小不会随着次数而递减,意思是每次遍历数组的大小是相同的,每次都要遍历1万次,这部分的遍历工作也是无效的,既然分析出弊端,我们接着往下看。

第三种

/**
     * 给定一个数组和n,输出第n大数
     * 不存在则返回0
     *
     * @param arr 数组
     * @return 第n大的数
     */
    public static int findNMaxNumberVersion3(int[] arr, int n) {
        if (arr == null || arr.length == 0 || n > arr.length){
            return 0;
        }
        for (int i = 0; i < n ;i++){
            int j = i + 1;
            while (j < arr.length){
                if (arr[j] > arr[i]){
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
                j++;
            }
        }
        return arr[n -1];
    }

这些写法只会遍历前n个数,而且解决了第二种方法每次遍历的数组大小相同的弊端,第0 个数我遍历arr.length次,第1个数,遍历的次数 arr.length -1 依次类推,如果有1万个元素,那么提升的效率就很明显了。

延伸

这道算法题还可以延伸成找到前n大个元素,就不是第n大元素,是前n大个元素,其实解法是相同的,只是会保存每次遍历的结果即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值