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

Posted 来老铁干了这碗代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四种解法剑指 Offer 39. 数组中出现次数超过一半的数字相关的知识,希望对你有一定的参考价值。

立志用最少的代码做最高效的表达


数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2

限制:
1 <= 数组长度 <= 50000


代码一:HashMap

做法:利用hashmap统计次数,最后输出出现次数最多的变量

时间复杂度:O(n)
空间复杂度:O(n)

显而易见的缺点:没有利用“出现次数超过一半”这个条件


    static class Solution1 {
        public int maxCount(int[] nums) {
            if(nums.length == 0) return -1;
            Map<Integer, Integer> map = new HashMap<>();
            int max = 0, max_value = -0x7fffffff, len = nums.length;
            for(int i = 0; i < len; i++) {
                if(map.putIfAbsent(nums[i],1) != null)      // 如果为空,则赋值为0
                    map.put(nums[i], map.get(nums[i])+1);
                if(max_value < map.get(nums[i])) { max_value = map.get(nums[i]); max = nums[i]; }
            }
            return max;
        }
    } 

代码二:针对代码一的优化

针对思路一的优化:因为出现次数超过一半即可,因此无需遍历完整张表,当某个值出现次数超过一半,结束循环,输出即可

时间复杂度:O(n/2)~O(n)
空间复杂度:O(n)

class Solution {
    public int maxCount(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        int max = 0, max_value = -0x7fffffff, len = nums.length;
        for(int i = 0; i < len; i++) {
            if(map.putIfAbsent(nums[i],1) != null)      // 如果为空,则赋值为0
                map.put(nums[i], map.get(nums[i])+1);
            if(map.get(nums[i]) > len/2)
                return nums[i];
        }
        return -1;
    }
}

代码三:排序算法

由于出现次数超过一半,因此排序后,数组的中间值一定为该数。

时间复杂度:O(nlogn)
空间复杂度:O(1)


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

代码四:摩尔投票法

可以理解为同归于尽大法,一个对一个,最后活下来的一定是出现次数超过一半的

class Solution {
    public int majorityElement(int[] nums) {
        int res = 0, count = 0;
        for(int i : nums)
            if(count == 0) {
                res = i; count++;
            }
            else
                count += (res==i ? 1 : -1);
        return res;
    }
}

完整可运行Java代码

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class 剑指Offer39_数组中次数超一半的数字 {
    // 1、hashmap:双O(n)
    // 做法:利用hashmap统计次数,最后输出出现次数最多的变量
    // 显而易见的缺点:没有利用“出现次数超过一半”这个条件
    static class Solution1 {
        public int maxCount(int[] nums) {
            if(nums.length == 0) return -1;
            Map<Integer, Integer> map = new HashMap<>();
            int max = 0, max_value = -0x7fffffff, len = nums.length;
            for(int i = 0; i < len; i++) {
                if(map.putIfAbsent(nums[i],1) != null)      // 如果为空,则赋值为0
                    map.put(nums[i], map.get(nums[i])+1);
                if(max_value < map.get(nums[i])) { max_value = map.get(nums[i]); max = nums[i]; }
            }
            return max;
        }
    }
    // 2、针对思路一的优化;因为出现次数超过一半即可,因此无需遍历完整张表,当某个值出现次数超过一半,结束循环,输出即可。
    // 时间O(n/2),空间O(n)
    static class Solution2 {
        public int maxCount(int[] nums) {
            Map<Integer, Integer> map = new HashMap<>();
            int max = 0, max_value = -0x7fffffff, len = nums.length;
            for(int i = 0; i < len; i++) {
                if(map.putIfAbsent(nums[i],1) != null)      // 如果为空,则赋值为0
                    map.put(nums[i], map.get(nums[i])+1);
                if(map.get(nums[i]) > len/2)
                    return nums[i];
            }
            return -1;
        }
    }

    // 3、排序:O(nlogn)、O(1)
    static class Solution3 {
        public int maxCount(int[] nums) {
            Arrays.sort(nums);
            return nums[nums.length/2];
        }
    }
    // 4、摩尔投票法,可以理解为同归于尽大法,一个对一个,最后活下来的一定是出现次数超过一半的
    static class Solution4 {
        public int majorityElement(int[] nums) {
            int res = 0, count = 0;
            for(int i : nums)
                if(count == 0) {
                    res = i; count++;
                }
                else
                    count += (res==i ? 1 : -1);
            return res;
        }
    }
    public static void main(String[] args) {

    }
}

以上是关于四种解法剑指 Offer 39. 数组中出现次数超过一半的数字的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

剑指OFFER 数字在排序数组中出现的次数

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

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