【489、给定一个数组arr,返回数量超过一半的数字,如果没有则返回-1】

116 阅读3分钟

投票算法实现的 Java 代码: 算法的基本思路:

1.初始化候选元素为0,计数器为0。 2.遍历数组中的每个元素。

  • 如果计数器为0,则将当前元素作为候选元素。
  • 如果当前元素与候选元素相同,则计数器加1,否则计数器减1。 3.计算候选元素的出现次数,如果超过数组长度的一半,则返回该元素;否则返回-1。
public class MajorityElement {
    public static int majorityElement(int[] arr) {
        int candidate = 0; // 候选元素初始化为0
        int count = 0; // 计数器初始化为0
        // 遍历数组中的每个元素
        for (int i = 0; i < arr.length; i++) {
            if (count == 0) { // 如果计数器为0,则将当前元素作为候选元素
                candidate = arr[i];
            }
            if (arr[i] == candidate) { // 如果当前元素与候选元素相同,则计数器加1
                count++;
            } else { // 如果当前元素与候选元素不同,则计数器减1
                count--;
            }
        }
        count = 0;
        // 计算候选元素的出现次数
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == candidate) {
                count++;
            }
        }
        // 如果候选元素的出现次数超过数组长度的一半,则返回该元素
        if (count > arr.length / 2) {
            return candidate;
        }
        // 否则返回-1
        return -1;
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 2, 2};
        int majority = majorityElement(arr);
        System.out.println("The majority element is: " + majority);
    }
}

直接计数实现的 Java 代码: 算法基本思路:

1.初始化计数器为1,将第一个元素作为候选元素。 2.遍历数组中的每个元素,如果当前元素与候选元素相同,则计数器加1,否则计数器减1。 3.如果计数器为0,则将当前元素作为候选元素,并将计数器重置为1。 4.如果候选元素的出现次数超过数组长度的一半,则返回该元素。 5.否则返回-1。

public class MajorityElement {
    public static int majorityElement(int[] arr) {
        int count = 1; // 计数器初始化为1
        int majority = arr[0]; // 候选元素初始化为第一个元素
        // 遍历数组中的每个元素
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] == majority) { // 如果当前元素与候选元素相同,则计数器加1
                count++;
            } else { // 如果当前元素与候选元素不同,则计数器减1
                count--;
            }
            if (count == 0) { // 如果计数器为0,则将当前元素作为候选元素,并将计数器重置为1
                majority = arr[i];
                count = 1;
            }
            // 如果候选元素的出现次数超过数组长度的一半,则返回该元素
            if (count > arr.length / 2) {
                return majority;
            }
        }
        // 否则返回-1
        return -1;
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 2, 2};
        int majority = majorityElement(arr);
        System.out.println("The majority element is: " + majority);
    }
}

这两种算法分别是 Boyer-Moore 投票算法和直接计数算法。它们都可以用来解决寻找数组中出现次数超过一半的元素的问题,但是实现方法略有不同。

Boyer-Moore 投票算法的核心思想是从数组头开始,不断消除不同的元素对,并维护一个候选元素,直到遍历完整个数组。在第一遍遍历过程中,我们维护一个候选元素以及一个计数器。如果遇到相同的元素,计数器加一;如果遇到不同的元素,计数器减一。如果计数器归零,那么我们就从当前位置开始,重新寻找候选元素,并重新开始计数。在第二遍遍历过程中,我们统计候选元素的出现次数,如果出现次数超过一半,则返回该元素;否则返回 -1。

直接计数算法的核心思想是遍历数组,统计每个元素的出现次数。在统计的同时,我们维护一个变量 maxCount 来记录出现次数最多的元素,以及一个变量 maxElement 来记录该元素的值。在遍历结束后,我们检查 maxCount 是否大于数组长度的一半,如果是则返回 maxElement;否则返回 -1。

推荐使用 Boyer-Moore 投票算法。因为它的时间复杂度和空间复杂度都比直接计数算法更低,而且更容易理解和实现。在实际的工程项目中,常常需要考虑时间和空间两个因素的综合,因此 Boyer-Moore 投票算法更适合用于大规模的数据处理。