好好刷力扣 | 169.多数元素 / 计数法、排序法、摩尔投票法

169.多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入:[3,2,3]
输出:3

一、计数法

用HashMap

class Solution {
    public int majorityElement(int[] nums) {
        HashMap<Integer,Integer> map=new HashMap<Integer,Integer> ();
        int m=0;
        for(int i=0;i<nums.length;i++){
            //记录每个元素出现次数
            if(map.containsKey(nums[i])){
                map.replace(nums[i],map.get(nums[i])+1);
                //当出现次数大于n/2,把这个值记录下来为m
                if(map.get(nums[i])>nums.length/2){
                    m=nums[i];                   
                }
            }else{
                map.put(nums[i],1);
            }
        }
        //特殊情况当n=1的时候,返回本身
        return nums.length==1?nums[0]:m;         
    }
}
空间复杂度:O(n)。
时间复杂度:O(n)

记笔记:

hashmap遍历:

 //第一种:普遍使用,二次取值
      System.out.println("通过Map.keySet遍历key和value:");
      for (String key : map.keySet()) {
       System.out.println("key= "+ key + " and value= " + map.get(key));
      }
      
      //第二种
      System.out.println("通过Map.entrySet使用iterator遍历key和value:");
      Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
      while (it.hasNext()) {
       Map.Entry<String, String> entry = it.next();
       System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
      }
      
      //第三种:推荐,尤其是容量大时
      System.out.println("通过Map.entrySet遍历key和value");
      for (Map.Entry<String, String> entry : map.entrySet()) {
       System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
      }

二、 排序法

数组中有出现次数大于 n/2 的元素,排好序之后的数组中,相同元素总是相邻的。举个例子:
无论是1 1 1 2 3,0 1 1 1 2还是-1 0 1 1 1,数组中间的元素总是“多数元素”。

class Solution {
    public int majorityElement(int[] nums) {
        Arrays.sort(nums);//排序
        return nums[nums.length/2];//排序之后,出现在中间的为多数元素
    }
}
时间复杂度:O(nlogn)。将数组排序的时间复杂度为 O(nlogn)。
空间复杂度:O(logn)。如果使用语言自带的排序算法,需要使用O(logn) 的栈空间。如果自己编写堆排序,则只需要使用 O(1)的额外空间。

三、 摩尔投票法.Boyer-Moore 算法

候选人(cand_num)初始化为nums[0],票数count初始化为1。
当遇到与cand_num相同的数,则票数count = count + 1,否则票数count = count - 1。当票数count为0时,更换候选人,并将票数count重置为1。
遍历完数组后,cand_num即为最终答案。

为何这行得通呢?
投票法是遇到相同的则票数 + 1,遇到不同的则票数 - 1。
且“多数元素”的个数> ⌊ n/2 ⌋,其余元素的个数总和<= ⌊ n/2 ⌋。
因此“多数元素”的个数 - 其余元素的个数总和 的结果 肯定 >= 1。
这就相当于每个“多数元素”和其他元素 两两相互抵消,抵消到最后肯定还剩余至少1个“多数元素”。

无论数组是1 2 1 2 1,亦或是1 2 2 1 1,总能得到正确的候选人。

参考

class Solution {
    public int majorityElement(int[] nums) {
        //初始化第一个元素为候选人nums1,初始票数count为1
        int nums1=nums[0];
        int count=1;
        //遍历其余的元素
        for(int i=1;i<nums.length;i++){
            //如果当前元素和候选人一样,则票数加1
            if(nums[i]==nums1){
                count++;
            }else{ //不一样,票数减1
                count--;
            }
            //遍历过程中,如果count=0,更换当前元素位候选人,票数count重置为1
             if(count==0){
                    nums1=nums[i];
                    count=1;
                }
        }
        return nums1;
    }
}

时间复杂度:O(n)O(n)Boyer-Moore 算法只对数组进行了一次遍历。
空间复杂度:O(1)O(1)Boyer-Moore 算法只需要常数级别的额外空间。

你可能感兴趣的:(好好刷力扣,leetcode,java,算法)