方式一:哈希表
哈希表中存储的键值是唯一的,用key存储数组元素,value用来存储元素出现的个数
class Solution {
public int majorityElement(int[] nums) {
if(nums==null || nums.length==0)
return 0;
HashMap<Integer,Integer> map = new HashMap();
for(int i=0;i<nums.length;i++)
{
if(!map.containsKey(nums[i]))
map.put(nums[i],1);
else
map.put(nums[i],map.get(nums[i])+1);
}
for(int num:map.keySet())
{
if(map.get(num)>nums.length/2)//某个元素出现的次数大于长度的一半,该数即为多数
return num;
}
return 0;
}
}
时间复杂度O(n)
空间复杂度O(n)
方式二:先排序,取中间元素【多数占半数以上】
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
}
时间复杂度 o(nlogn)【排序消耗】
空间复杂度 o(1)
方法三:分治(递归)
1、每次对半分,去找左右两边的多数元素,然后在左右合并的区间中确定当前区间的多数元素是左边还是右边的,把无数个小区间的多数元素找出来,然后进行区间合并,最后找出大区间的多数元素
2、分到只剩一个元素(终止条件)此时多数元素是它自己
为什么可以用递归?
大问题拆解成子问题
存在终止条件
大问题和小问题的求解方式相同
class Solution {
public int majorityElement(int[] nums) {
return getMajority(nums,0,nums.length-1);
}
public int getMajority(int[] nums,int left,int right)
{
if(left==right)
return nums[left];//这里返回right也行
int mid=left+(right-left)/2;
int leftMajority=getMajority(nums,left,mid);
int rightMajority=getMajority(nums,mid+1,right);
if(leftMajority==rightMajority)//左右多素元素相同,返回其中之一这里选左多数
return leftMajority;
//不同,则计算此区间内左右两个子区间“多数元素”分别出现的次数,返回其大
int leftCount=0;
int rightCount=0;
for(int i=left;i<=right;i++)
{
if(nums[i]==leftMajority)
leftCount++;
else if(nums[i]==rightMajority)
rightCount++;
}
//左边多数元素出现次数大于右边,返回左多数元素,否则返回右边,这里是左右区间合并成大区间的比较
return leftCount>rightCount?leftMajority:rightMajority;
}
}
空间复杂度是logn,单边递归栈的压入
时间复杂度nlogn 主定理?