最有效的方法来搜索数字在排序数组中出现的次数

时间:2016-06-09 16:23:06

标签: java arrays

我正在寻找一种有效的方法来查找特定数字在排序数组中出现的次数。

我目前的代码:

public class Numbers {

    public static void main(String[] args) {
        int[] x = new int[]{1,2,3,4,4,7,7,7,7,7,8};
        int count = 0;
        for (int i = 0; i < x.length; ++i)
            if (x[i] == 7) ++count;
        System.out.println(count);
    }
}

2 个答案:

答案 0 :(得分:3)

由于数组已按照注释中的说明进行排序,因此您可以执行2次二进制搜索,以查找数字中出现数字的最低索引以及出现数字的最高索引。添加二进制搜索以查找某些索引,并获得O(log n)算法。

使用一些不同的数组值尝试此代码。

public static void main(final String[] args) {
    final int numberToCount = 7;

    final int[] x = new int[]{1,2,3,4,4,6,6,6,6,7,7,7,7,7,8,8,8,8,8,8};

    final int indexOfKnownOccurence = Arrays.binarySearch(x, numberToCount);
    if (indexOfKnownOccurence < 0) {
        System.out.println("No instances of the number found");
        return;
    }

    final int lowerBound = findIndexOfFirstOccurence(x, numberToCount, 0, indexOfKnownOccurence);

    final int upperBound = findIndexOfLastOccurence(x, numberToCount, indexOfKnownOccurence, x.length - 1);

    System.out.println("Lower bound: " + lowerBound);
    System.out.println("Upper bound: " + upperBound);
    System.out.println("Number of occurrences: " + (upperBound - lowerBound + 1));
}

//Binary search for start index
public static int findIndexOfFirstOccurence(final int[] x, final int numberToFind, final int startIndex, final int endIndex) {
    if (startIndex == endIndex) {
        return startIndex;
    } else if (x[startIndex] == numberToFind) {
        return startIndex;
    } else if (startIndex + 1 == endIndex) {
        return endIndex;
    }

    final int midIndex = startIndex + (int)Math.floor((endIndex - startIndex) / 2);

    if (x[midIndex] == numberToFind) {
        return findIndexOfFirstOccurence(x, numberToFind, startIndex, midIndex);
    } else {
        return findIndexOfFirstOccurence(x, numberToFind, midIndex, endIndex);
    }
}

//Binary search for end index
public static int findIndexOfLastOccurence(final int[] x, final int numberToFind, final int startIndex, final int endIndex) {
    if (startIndex == endIndex) {
        return endIndex;
    } else if (x[endIndex] == numberToFind) {
        return endIndex;
    } else if (startIndex + 1 == endIndex) {
        return startIndex;
    }

    final int midIndex = startIndex + (int)Math.floor((endIndex - startIndex) / 2);

    if (x[midIndex] == numberToFind) {
        return findIndexOfLastOccurence(x, numberToFind, midIndex, endIndex);
    } else {
        return findIndexOfLastOccurence(x, numberToFind, startIndex, midIndex);
    }
}

答案 1 :(得分:1)

答案实际上取决于你的阵列有多长,如果它只有几十个元素,那么进行线性扫描可能更有效。如果它是一个更大的数组,我建议使用Array.binarySearch(),如下所示:

public static void main(String[] args) {
    int[] x = new int[]{1,2,3,4,4,7,7,7,7,7,8};
    int index = Arrays.binarySearch(x, 7);
    System.out.println(index);
    int count = 0;
    if (index >= 0) {
        // search down
        int i = index - 1;
        for (; i >= 0 && x[i] == 7; --i) {
        }
        // search up
        for (++index; index < x.length && x[index] == 7; ++index) {
        }
        count = index - (i + 1);
    }
    System.out.println(count);
}

首先二进制搜索会告诉你这个项目是否存在于数组中,如果是,你真的不知道搜索找到元素的范围,但是你必须在两者中进行线性扫描确定准确计数的方向,但是您必须做的比较次数最多是此特定键的计数...(不包括二进制搜索)