用最少的比较次数在数组中找到第二大的元素

74

对于大小为N的数组,需要多少比较次数?


2
你被允许使用多少临时存储空间? - Michael Myers
2
@Sachin,这将会是n*log(n)次比较。排序不能更快了。 - riwalk
2
@Stargazer712:除非数组是整数。然后,您可以使用基数排序,完全不需要比较 ;-) - Steve Jessop
1
更一般地说,查找第k大的元素:https://dev59.com/UnVC5IYBdhLWcg3wjyDu - Nate Kohl
2
@Stargazer712:不需要边界:http://en.wikipedia.org/wiki/Radix_sort#In-place_MSD_radix_sort_implementations。想一想,基数排序仍然涉及循环输入数据,并且循环必须涉及终止条件的比较。它不需要是一个*有序*比较,只需要是一个相等比较。但你是对的,问题没有提到数据类型,因此正确的答案必须假定不透明数据和比较器函数。如果面试官犯了一个“int”特例(或者在真正的推动中使用字符串),那么就是0次比较... - Steve Jessop
显示剩余9条评论
23个回答

0

我想,按照上面所说的“最优算法使用n+log n-2次比较”,我想出了以下不使用二叉树存储值的代码:

在每个递归调用期间,数组大小减半。

因此,比较的数量为:

第一次迭代:n/2次比较

第二次迭代:n/4次比较

第三次迭代:n/8次比较

... 直到log n次迭代?

因此,总共 => n - 1次比较?

function findSecondLargestInArray(array) {
    let winner = [];
    if (array.length === 2) {
        if (array[0] < array[1]) {
            return array[0];
        } else {
            return array[1];
        }
    }
    for (let i = 1; i <= Math.floor(array.length / 2); i++) {
        if (array[2 * i - 1] > array[2 * i - 2]) {
            winner.push(array[2 * i - 1]);
        } else {
            winner.push(array[2 * i - 2]);
        }
    }
    return findSecondLargestInArray(winner);
}

假设数组包含2的n次幂个数字。
如果有6个数字,则会有3个数字移动到下一个级别,这是不正确的。
需要像8个数字=>4个数字=>2个数字=>1个数字=>2的n次方个数字。

-2
package com.array.orderstatistics;

import java.util.Arrays;
import java.util.Collections;

public class SecondLargestElement {

    /**
     *  Total Time Complexity will be n log n + O(1)
     * @param str
     */
    public static void main(String str[]) {
        Integer[] integerArr = new Integer[] { 5, 1, 2, 6, 4 };



        // Step1 : Time Complexity will be n log(n)
        Arrays.sort(integerArr, Collections.reverseOrder());

        // Step2 : Array.get Second largestElement
        int secondLargestElement = integerArr[1];

        System.out.println(secondLargestElement);
    }
}

你忘记了计算比较次数的部分。(提示:在调用“Arrays.sort()”时有很多隐藏的比较。) - Toby Speight
感谢您的评论,我现在已经纠正了代码。 最近JDK中的Arrays.sort(int[] a)是使用双轴快速排序算法实现的,平均复杂度为O(n log n),并且是原地执行(例如不需要额外的空间)。因此,这个程序的总时间复杂度将是O(n log n) + O(1)。 - Yuvaraj Ram
请在您的代码中添加一些解释!这样做会更容易理解。 - Arnav Borborah

-3
将数组按升序排序,然后将一个变量赋值为第(n-1)个项。

2
非常低效。根据定义需要n*log(n)次比较。 - riwalk
使用暴力或锦标赛方法,在暴力中,第一次比较将需要n-1次,并删除最大值,第二次将需要n-2 = n-1 + n-2 = 2n-3次比较,时间复杂度为O(1)和T(1)。使用锦标赛方法,您需要确保有2的幂元素,否则将添加其他数字到数组中,并将比较减少到n + logn - 2(logn用于创建锦标赛,n-1用于查找输给锦标赛中最大值的元素)。 - Mr X

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接