【菜鸟训练】剑指 Offer 39. 数组中出现次数超过一半的数字

题目描述:

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

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

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

代码:

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

/**
 * @author :xxx
 * @description:TODO
 * @date :2021/10/19 17:18
 */
public class jianzhi39 {

    /*
        哈希,将数组中出现的数及其出现的次数存到map中,这样我们就只需要找对应的map中最大的value所对应的key即可。
        时间复杂度:O(nums.length)
        空间复杂度:O(nums.length)
     */
    public int majorityElement(int[] nums) {
        Map<Integer,Integer> map = new HashMap<>();

        for (int num : nums){
            if (!map.containsKey(num)){
                map.put(num,1);
            }
            else {
                map.put(num,map.get(num)+1);
            }
        }

        int ansk = -1,ansv = -1;
        for (Map.Entry<Integer,Integer> entry : map.entrySet()){
            if (entry.getValue() > ansv){
                ansk = entry.getKey();
                ansv = entry.getValue();
            }
        }
        return ansk;
    }

    /*
    排序
    时间复杂度O(NlogN)
    空间复杂度O(logN)
     */
    public int majorityElement1(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length/2];
    }

    /*
    摩尔选举法:该问题其实就是有一群候选人,其中一个候选人得票数大于总投票数的一半,让你找到这个候选人,所以可以使用摩尔选举。
              我们将情况只分为两种:值为A,值不为A,cnt用来统计A的个数,cand就是A。
              当num值为A时,我们将cnt+1,当值不为A的时候,我们将cnt-1,当cnt为0时,我们取下一个数,将其重新作为A。
              这样当我们遍历完一边数组时,所得到的cand一定就是我们要寻找的众数。
    时间复杂度:O(N)
    空间复杂度:O(1)
     */
    public int majorityElement2(int[] nums) {
        int cnt = 0;
        int cand = 0;
        for (int num : nums){
            if (cnt == 0){
                cand = num;
            }
            cnt += (cand == num) ? 1 : -1;
        }
        return cand;
    }

    public static void main(String[] args) {
        jianzhi39 obj = new jianzhi39();
        System.out.println(obj.majorityElement2(new int[]{1, 2, 3, 2, 2, 2, 5, 4, 2}));
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值