剑指 Offer 39. 数组中出现次数超过一半的数字

方法1:排序
思路:先排序,然后返回arr[arr.length / 2]
代码:
排序
class Solution {
    public int majorityElement(int[] nums) {
        quickSort(nums, 0, nums.length - 1);
        return(nums[nums.length / 2]);
    }

    public static void quickSort(int[] arr, int start, int end){
        if(start >= end)return;
        int mid = adjust(arr, start, end);
        quickSort(arr, start, mid - 1);
        quickSort(arr, mid + 1, end);
    }

    public static int adjust(int[] arr, int start, int end){
        int pivot = arr[start];
        int l = start + 1;
        int r = end;
        while(l < r){
            //从左往右,找到第一个比pivot大的数
            while(l < r && arr[l] <= pivot)l++;
            //找到第一个比pivot小的数
             while(l < r && arr[r] >= pivot)r--;
             if(l < r){
                 swap(arr, l, r);
                 l++;
                 r--;
             }
        }

        //对于l==r的最后情况单独处理,然后返回中间的分界下标
        if(l == r && pivot < arr[r]){
            r--;
        }
        swap(arr, start, r);
        return r;
    }

    public static void swap(int[] arr, int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}
复杂度分析:由于采用了快排,时间为o(n log(n)),空间log(n)
方法2:使用哈希表
思路:将所有元素存入哈希表,key为元素,value为元素出现的次数,再遍历哈希表得到元素的出现次数。需要注意的是,使用map.get()时,需要做是否包含元素判断,不能使用一下写法。
代码:
//哈希表
class Solution {
        public int majorityElement(int[] nums) {
            //Map<num, count>存储数字和出现次数
           HashMap<Integer, Integer> map = new HashMap<>();
           for(int num : nums){
               if(map.containsKey(num)){
                   //HashMpa的put方法会覆盖掉之前的key和value
                   map.put(num, map.get(num) + 1);
               }else{
                   map.put(num, 1);
               }
           }

           for(Map.Entry<Integer, Integer>entry : map.entrySet()){
               if(entry.getValue() > nums.length / 2){
                   return entry.getKey();
               }
           }
           return -1;
    }
}
复杂度分析:时间空间都为0(n)

在这里插入图片描述

方法3,boyer-morre
思路:当计数器为0时就将当前元素选为众数,使用ans保存,如果ans与当前元素相同,则count+1,不同则count-1,扫描一次数组,返回最后的ans即可。
代码:
//Boyer-Morre投票法
//当计数器为0时就将当前元素选为众数,如果与当前元素相同,则+1,不同则-1,扫描一次数组即可。
class Solution {
        public int majorityElement(int[] nums) {
            int count = 1, ans = nums[0];
            for(int i = 1; i < nums.length; i++){
                if(count == 0)ans = nums[i];
                count = count + (nums[i] == ans ? 1 : -1); 
            }
            return ans;
    }
}
复杂度分析:时间为o(n),空间为o(1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值