基于摩尔投票算法求解整型数组中的多数元素 | 豆包MarsCode AI刷题

79 阅读4分钟

一、问题分析

在这个有趣的编程问题中,我们面临着从整型数组里找出占比超过一半的数的挑战。就像小 R 所面临的情况,从班级同学给出的数字集合中找到那个特殊的、出现频率极高的数字。这一问题的关键在于如何在众多数字中快速且准确地识别出这个具有优势占比的元素。如果采用简单直观的方法,比如对每个数字进行计数并比较,时间复杂度会很高,因为需要双重遍历数组,在处理大规模数据时效率低下。因此,我们需要一种更高效的算法来解决这个问题。

二、解题思路

为了解决此问题,我们运用了摩尔投票算法。这个算法的核心思想是基于多数元素在数组中的特殊性,它在抵消其他元素的过程中仍能保持优势。具体步骤如下:

首先,我们初始化两个重要的变量。candidate变量用于存储当前候选的多数元素,count变量则用于记录这个候选元素的出现计数。然后,我们开始遍历整个数组。当count的值为 0 时,意味着当前没有确定的候选元素,此时我们将当前遍历到的数组元素num赋值给candidate,并将count设为 1,表示找到了一个可能的多数元素候选者。在后续遍历过程中,如果当前元素numcandidate相同,说明找到了一个相同的元素,那么count的值就增加 1;反之,如果numcandidate不同,就将count的值减 1。这种增减操作模拟了不同元素之间的 “抵消” 过程。

经过一轮遍历后,我们得到了一个candidate元素,但这还不能确定它就是真正的多数元素。因为在一些特殊情况下,这个candidate可能是在 “抵消” 过程中误选出来的。所以,我们需要再次遍历数组,对candidate元素进行验证,统计它在数组中的实际出现次数。如果其出现次数大于数组长度的一半,那么它就是我们要找的多数元素。

public class Main {
    public static int solution(int[] array) {
        int candidate = 0;
        int count = 0;
        // 遍历数组,找出候选元素
        for (int num : array) {
            if (count == 0) {
                candidate = num;
                count = 1;
            } else if (num == candidate) {
                count++;
            } else {
                count--;
            }
        }
        // 验证候选元素是否确实出现次数超过一半
        count = 0;
        for (int num : array) {
            if (num == candidate) {
                count++;
            }
        }
        if (count > array.length / 2) {
            return candidate;
        } else {
            throw new IllegalArgumentException("No majority element found");
        }
    }
    public static void main(String[] args) {
        System.out.println(solution(new int[]{1, 3, 8, 2, 3, 1, 3, 3, 3}) == 3);
        System.out.println(solution(new int[]{5, 5, 5, 1, 2, 5, 5}) == 5);
        System.out.println(solution(new int[]{9, 9, 9, 9, 8, 9, 8, 8}) == 9);
    }
}

三、代码实现复杂度分析

(一)时间复杂度

代码实现中,主要有两次遍历数组的操作。第一次遍历通过摩尔投票算法找出候选元素,这个过程中每个元素都被遍历一次,时间复杂度为 ,其中 是数组的长度。第二次遍历用于验证候选元素的出现次数,同样每个元素被遍历一次,时间复杂度也是 。因此,整个算法的时间复杂度是 。这种线性时间复杂度的算法在处理大规模数据时表现出了良好的性能。

(二)空间复杂度

在整个代码中,我们只使用了两个额外的变量candidatecount,它们所占用的空间是固定的,不随数组长度的变化而变化。所以,算法的空间复杂度为 ,这是一种非常高效的空间利用方式。

四、总结

通过对这个整型数组中寻找占比超过一半元素问题的深入分析和使用摩尔投票算法的解决方案,我们深刻体会到了算法选择的重要性。合适的算法能够在保证结果正确的前提下,极大地提高程序的效率。在这个问题中,摩尔投票算法巧妙地利用了多数元素的特性,避免了对每个元素的繁琐计数和比较。同时,对代码实现复杂度的分析让我们清晰地了解了算法在时间和空间上的性能表现。在实际的编程实践中,无论是处理类似的数组问题还是其他类型的算法问题,我们都应该深入理解问题的本质,选择合适的算法,并对算法的复杂度进行评估,这样才能编写出高效、优质的代码,更好地应对各种复杂的编程挑战。