28. 数组中出现次数超过一半的数字

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

解题思路

多数投票问题,可以利用 Boyer-Moore Majority Vote Algorithm 来解决这个问题,使得时间复杂度为 O(N)。

出现的次数超过数组长度的一半,表明这个数字出现的次数比其他数出现的次数的总和还多。

考虑每次删除两个不同的数,那么在剩下的数中,出现的次数仍然超过总数的一般,不断重复该过程,排除掉其他的数,最终找到那个出现次数超过一半的数字。这个方法的时间复杂度是O(N),空间复杂度是O(1)。

换个思路,这个可以通过计数实现,而不是真正物理删除。在遍历数组的过程中,保存两个值,一个是数组中数字,一个是出现次数。当遍历到下一个数字时,如果这个数字跟之前保存的数字相同,则次数加1,如果不同,则次数减1。如果次数为0,则保存下一个数字并把次数设置为1,由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为1时对应的数字。

public int MoreThanHalfNum_Solution(int[] nums) {
    int majority = nums[0];
    for (int i = 1, cnt = 1; i < nums.length; i++) {
        cnt = nums[i] == majority ? cnt + 1 : cnt - 1;
        if (cnt == 0) {
            majority = nums[i];
            cnt = 1;
        }
    }
    int cnt = 0;
    for (int val : nums)
        if (val == majority)
            cnt++;
    return cnt > nums.length / 2 ? majority : 0;
}

你可能感兴趣的:(28. 数组中出现次数超过一半的数字)