Day28:数组中出现次数超过一半的数字

时间:2022-07-24
本文章向大家介绍Day28:数组中出现次数超过一半的数字,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

剑指Offer_编程题——数组中出现次数超过一半的数字

题目描述:

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

具体要求:

时间限制: C/C++ 1秒,其他语言2秒 空间限制: C/C++32M,其他语言64M

具体思路:

思路一   这是我们最常规的一种思维,最简单的一种算法。就是定义一个计数器count来计数,首先遍历整个数组。一次计算出现的次数。将出现最大的数字的次数与数组长度的一半相比较。如果大于数组一半的长度,输出这个数,否则输出0,具体我们用Java来将其实现。

public class Solution{
	public int MoreThanHalfNum_Solution(int [] array){
		int len = array.length;
		int k = array[0];
		int count = 1;
		for(int i = 1; i < len; i++){
			if(k == array[i]){
				count++;
			}
			else if(k != array[i]){
				count--;
			}if(count == 0){
				k = array[i];
				count = 1;
			}
		}
		int num = 0;
		for(int j = 0; j < len; j++){
			if(array[j] == k){
				num++;
			}
		}
		if(num * 2 <= len){
			return 0;
		}else{
			return k;
		}
	}
}

代码效果图如图所示:

思路二   先用Boyer-Moore Majority-Vote Algorithm算法,即多数投票问题,找出序列中出现次数超过一半的元素。在判断题目的条件时,看是否出现次数超过一半,超过则存在。并不超过则不存在。   Boyer-Moore Majority Vote Algorithm算法: 使用count来统计一个元素出现的次数,当遍历到的元素和统计元素相等时,令count++,否则令count–。如果前面查找了i个元素,且count==0,说明前i个元素没有most,或者有most,但是出现的次数小于i/2,因为如果i/2超过数组一半时count就一定不会为0.此时剩下的n-i个元素中,most数目依然多于(n-i)/2,因此继续查找就能找出majority。我们用java将其实现

public class Solution{
	public int MoreThanHalfNum_Solution(int []array){
		if(array == null || array.length == 0){
			return 0;
		}
		int most = array[0];
		int count = 1;
		for(int i = 1; i < array.length; i++){
			count = most == array[i]?count+1:count-1;
			if(count == 0){
				most = array[i];
				count = 1;
			}
		}
		count = 0;
		for(int i = 0; i < array.length;i++){
			if(most == array[i]){
			count++;
			}
		}
			return count > array.length/2?most:0;
	}
}

代码效果图如图所示:

思路三   可以采用Python中的字典的方法,元素对应key,出现的次数对应val。具体实现如下:

class Solution:
	def MoreThanHalfNum_Solution(self, numbers):
		if numbers == []:
			return 0
		dictonary = {}
		dictonary = dictonary.fromkeys(numbers, 0)
		for num in numbers:
			dictonary[num] += 1
		for key in dictonary.keys():
			if dictonary[key] * 2 > len(numbers):
				return key
		return 0

代码效果图如图所示:

思路四   如果一个数字的个数超过半数,那么N/2大的数字一定是这个数字,因此用这个方法找出第N/2大的数字,然后判断这个数字出现的次数是不是满足大于长度的二分之一。(N维数组的长度)。具体用python将其实现:

class Solution:
    def partitionOfK(self, numbers, start, end, k):
        if k < 0 or numbers == [] or start < 0 or end >= len(numbers) or k > end:
            return None
        low = start
        high = end
        key = numbers[start]
        while low < high:
            while low < high and numbers[high] >= key:
                high -= 1
            numbers[low] = numbers[high]
            while low < high and numbers[low] <= key:
                low += 1
            numbers[high] = numbers[low]
        numbers[low] = key
        if low < k:
            return self.partitionOfK(numbers, start + 1, end, k)
        elif low > k:
            return self.partitionOfK(numbers, start, end - 1, k)
        else:
            return numbers[low]
    def checkMoreThanHalf(self, numbers, num):
        times = 0
        for number in numbers:
            if num == number:
                times += 1
        if times * 2 <= len(numbers):
            return False
        return True
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        if numbers == []:
            return 0
        result = self.partitionOfK(numbers, 0, len(numbers) - 1, len(numbers) >> 1)
        if self.checkMoreThanHalf(numbers, result):
            return result
        else:
            return 0

代码效果图如图所示:

思路五   数组中如果有一个数字出现的次数超过数组长度的一半,也就是说他出现的次数比其他所有的数字出现的次数和还要多。因此当我们遍历到下一个数字的时候,如果相同,次数加1,不同次数减1,知道为0,如果为0,那么保存下一个数字,并把次数设置为1,找的就是最后设置为1 的数字。接下来用python实现:

class Solution:
	def checkMoreThanHalf(self, numbers, num):
		times = 0
		for number in numbers:
			if num == number:
				times += 1
		if times * 2 <= len(numbers):
			return False
		return True
	def MoreThanHalfNum_Solution(self, numbers):
		if numbers == []:
			return 0
		result = numbers[0]
		times = 1
		for i in range(1, len(numbers)):
			if times == 0:
				result = numbers[i]
				times = 1
			elif numbers[i] == result:
				times += 1
			else:
				times -= 1
		if self.checkMoreThanHalf(numbers, result):
			return result
		else:
			return 0

代码效果图如图所示:

总结

  本道题主要考察数组的实际应用,一道很简单的算法编程题,但是本文一共应用了5种解法,其中前两种方法是用java实现的,并且还应用了著名的投票选举算法。后三种方法是用python实现的。三种方法其中用到了字典,以及还有两种相似但完全不同的方法。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!

参考文献

[1] 喜欢唱跳有错吗 [2] IDEA_TEYU_1112 [3] hustfc