其他分享
首页 > 其他分享> > 力扣 - 剑指 Offer 39. 数组中出现次数超过一半的数字

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

作者:互联网

题目

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

思路1(排序)

代码

class Solution {
    public int majorityElement(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length/2];
    }
}

复杂度分析

思路2(哈希表)

代码

class Solution {
    public int majorityElement(int[] nums) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int n : nums) {
            map.put(n, map.getOrDefault(n, 0) + 1);
        }

        int max = 0;
        int res = 0;
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            if (max < entry.getValue()) {
                max = entry.getValue();
                res = entry.getKey();
            }
        }
        return res;
    }
}

复杂度分析

思路3(分治)

代码

class Solution {
    public int majorityElement(int[] nums) {
        return majorityElementRec(nums, 0, nums.length-1);
    }

    public int majorityElementRec(int[] nums, int lo, int hi) {
        // 如果只有一个元素,那么直接返回
        if (lo == hi) {
            return nums[lo];
        }

        // 获取中间值
        int mid = lo + (hi - lo) / 2;
        // 递归左边和右边,直到剩下一个元素
        int left = majorityElementRec(nums, lo, mid);
        int right = majorityElementRec(nums, mid+1, hi);

        // 相等只需要返回一个
        if (left == right) {
            return left;
        }

        // 计算left和right在lo~hi范围中的出现的次数
        int leftCount = countInRange(nums, left, lo, hi);
        int rightCount = countInRange(nums, right, lo, hi);

        // 返回出现次数多的数
        return leftCount > rightCount ? left : right;
    }

    // 统计目标数字在指定范围出现的次数
    public int countInRange(int[] nums, int target, int lo, int hi) {
        int count = 0;
        for (int i = lo; i <= hi; i++) {
            if (nums[i] == target) {
                count++;
            }
        }
        return count;
    }
}

复杂度分析

思路4(摩尔投票法)

代码

class Solution {
    public int majorityElement(int[] nums) {
        // 代表结果的众数
        int res = nums[0];
        // 统计票数
        int votes = 0;

        for (int i = 0; i < nums.length; i++) {
            // 刚开始是0票,所以把数组的第一个元素作为众数
            // 如果以后的循环votes票数被抵消掉了为0,那么下一个元素就作为众数
            if (votes == 0) {
                res = nums[i];
            }
            // 和当前众数相同的,那么票数就加1
            if (res == nums[i]) {
                votes++;
            } else {
                // 如果和当前票数不同,票数就被抵消掉了一个
                votes--;
            }
        }
        
        return res;
    }
}

复杂度分析

标签:39,nums,int,res,票数,Offer,votes,力扣,众数
来源: https://www.cnblogs.com/linzeliang1222/p/15431523.html