数据结构与算法应用(四):Majority Number II

本文介绍了一种在数组中寻找出现频率超过数组长度三分之一的多数元素的方法,通过使用哈希表来实现,同时提供了一个贪心算法的解决方案,以及其时间复杂度和空间复杂度的分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

No.1-2 Majority Number II
Given an array of integers, the majority number is the number that occurs
more than 1/3 of the size of the array. Find it.

Note There is only one majority number in the array

Example For [1, 2, 1, 2, 1, 3, 3] return 1

/**
 * 
 * @author 风的流向
 * 
 */
public class MajorityNumber2 {
	/**
	 * @param nums
	 *            : A list of integers
	 * @return: The majority number that occurs more than 1/3
	 */
	static public int majorityNumber(ArrayList<Integer> nums) {
		// 想不到时间复杂度为n,空间复杂度为1的做法了,这里只好使用空间换时间的hash表去做
		Map<Integer, Integer> map = new HashMap<>();
		int count = nums.size() / 3;
		for (Integer num : nums) {
			int sum = 1;
			if (map.containsKey(num))
				sum = map.get(num) + 1;
			map.put(num, sum);
			if (sum > count) {
				return num;
			}
		}
		return -1;
	}
}

【附:开课吧算法讨论组参考答案】
http://www.douban.com/group/topic/68473876/

[题解] Majority Number 贪心算法
总体思路就是从数组第一个数字开始,并把第一个数字作为majority candidate(众数候选者),然后用一个计数器统计majority candidate的出现次数。
int idxMajority = 0; //指向众数候选者
int cntMajority = 1; //计数器

然后开始遍历整个数组,如果后面的数字和majority candidate一致,则计数器加1,继续往后走;

如果后面的数字和majority candidate不一致,则计数器减1,此时要判断一下计数器是否为0:
a. 如果不为0,则继续往后走;
b. 如果为0,那么说明前面的子数组(从idxMajority到当前index)中有一半是同一个数字,即为majority candidate,另一半为不同的数字,此时如果舍弃前面的子数组,则并不会导致majority number产生变化。
进一步解释一下,这里其实还会有两种情况,即:
a’ 众数候选者,其实不是真正的众数,那么舍弃的子数组包含的都不是众数,这样不会对最终的结果影响。
b’ 众数候选者,是真正的众数,也不会对最终的结果产生影响。举个例子,7局4胜的乒乓球比赛,如果前两局打成1比1平,那么我们可以认为7局4胜,就变成了5局3胜,前面打的两局对整个比赛的结果没有影响,双方又回到了起跑线上。

直到循环结束,idxMajority指向的数组元素,即为majority candidate。

此题的关键为贪心策略 - 如何在遍历过程中保证局部最优解为整体最优解,即在循环结束时,所保持的majority candidate和原始数组的majority candidate是一样的,或者说前面舍弃的子数组,不会导致majority number有变化。

参考代码:

int majorityNumber(vector<int> nums) 
{ 
	// write your code here 
	int idxMajority = 0; 
	int cntMajority = 1; 
	
	for(int i = 1; i < nums.size(); i++) 
	{ 
		if(nums[idxMajority] == nums[i]) 
			cntMajority ++; 
		else 
			cntMajority --; 
		
		if(cntMajority == 0) 
		{ 
			i++; 
			idxMajority = i; 
			cntMajority = 1; 
		} 
	} 
	return nums[idxMajority]; 
} 

测试为19ms

ii和iii应该是类似的解法变形。
提示是iii里的复杂度要求为
O(n) time and O(k) extra space

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值