一、问题描述:
Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋
times.
You may assume that the array is non-empty and the majority element always exist in the array.
首先说下这道题的前提条件:保证存在个数大于 ⌊ n/2 ⌋ 的Majority Element
然后说一下自己拿到题目的“垃圾”方法:排序O(nlogn),取排序后的nums[n/2]即可,无空间要求。
最后请出献上膝盖的答案O(n):ans为答案初始化为0,cnt为初始化为0的计数器。
线性扫描nums,设当前扫描点为nums[i]:则ans必为nums[0]~nums[i-1]之间的某数
如果cnt == 0, 则ans=nums[i], 说明当前ans在nums[0]~nums[i-1]之间出现次数<= 非ans的出现次数之和,于是可保证原问题的ans与nums[i]~nums[n-1]中的ans相同,因为nums[0]~nums[i-1]之间没有提供足够多的ans来支持原问题==================这也是这道题归类到分治的原因,不过与大多数分治不同的是,子问题随着i的扫描在缩小。(也有人说这是DP)
若nums[i] == ans, 则计数器cnt++
若nums[i] != ans, 则计数器cnt--
该方法来自上世纪80年代的一篇论文研究结果 http://www.cs.utexas.edu/~moore/best-ideas/mjrty/
三、源码:
import java.util.*;
import java.io.*;
public class MajorityElement {
public int majorityElement(int[] nums) {
int len = nums.length;
if (len == 0) return 0;
int cnt=0, ans=0;
for (int i = 0; i < len; i++) {
if (cnt == 0) {
ans = nums[i];
cnt++;
}
else if (nums[i] == ans) cnt++;
else cnt--;
}
return ans;
}
public static void main(String[] args) {
int[] nums = new int[Integer.parseInt(args[0])];
Scanner scan = new Scanner(System.in);
for (int i = 0; i < nums.length; i++) {
nums[i] = scan.nextInt();
}
MajorityElement me = new MajorityElement();
System.out.println(me.majorityElement(nums));
}
}