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