169. 多数元素(java实现)--LeetCode

题目:

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

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

示例 2:

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

进阶:

  • 尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。

解法1:排序

/**
 * 思路:
 * 排序后中间的数就是众数
 */
    public int majorityElement(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length/2];
    }

时间复杂度:Onlogn

空间复杂度:O1

在这里插入图片描述

解法2:随机数

/**
 * 思路:
 * 随机挑一个数,大概率是众数
 */
    public int majorityElement(int[] nums) {
        while (true) {
            int random_num = randomGetNum(nums);
            boolean result = isMajority(random_num,nums);
            if (result) return random_num;
        }
    }

    private boolean isMajority(int random_num, int[] nums) {
        int count=0;
        for (int num:nums){
            if (num==random_num)count++;
        }
        return count>nums.length/2;
    }

    private int randomGetNum(int[] nums) {
        Random random = new Random();
        int index = random.nextInt(nums.length);
        return nums[index];
    }

时间复杂度:On^2

空间复杂度:O1

在这里插入图片描述

解法3:位运算

    /**
     * 思路:
     * 核心思路:众数超过数组的一半,也就意味着其二进制位上的每一个数都超过数组的一半
     */
    public int majorityElement(int[] nums) {
        int result = 0, k = nums.length >> 1;
        //符号位所以只能到31
        for (int i = 0; i < 32; i++) {
            int count = 0;
            for (int num : nums) {
                //num右移i后其二进制是否为1。也就是第i为二进制是否为1
                count += num >> i & 1;
                if (count > k) {
                    //众数通过不断的累加其二进制位的十进制值,最后就组成一个完整的十进制众数
                    result += 1 << i;
                    break;
                }
            }
        }
        return result;
    }

时间复杂度:On

空间复杂度:O1

在这里插入图片描述

或者这样写

    public int majorityElement(int[] nums) {
        int[] bits = new int[32];
        for (int num : nums){
            for (int i=0;i<bits.length;i++){
                if (((num>>i)&1)==1)bits[i]++;
            }
        }
        int result=0;
        for (int i=0;i<bits.length;i++){
            if (bits[i]>nums.length/2)result+=(1<<i);
        }
        return result;
    }

时间复杂度:On^2

空间复杂度:On

在这里插入图片描述

解法4:分治

/**
 * 思路:
 * 分治:查整个数组的众数,可以分解为子问题:比较左右两边的众数
 * 切分数组,比较左右两边的众数
 * 如果众数一样就返回
 * 不一样就比较左右众数的个数,多的那个就是众数
 */
    public int majorityElement(int[] nums) {
        return recursive(0,nums.length-1,nums);
    }

    private int recursive(int left, int right, int[] nums) {
        if (left==right)return nums[left];
        int mid=(left+right)/2;
        int l_majority = recursive(left, mid, nums);
        int r_majority = recursive(mid + 1, right, nums);
        int l_m_count=getCount(l_majority,left,right,nums);
        int r_m_count=getCount(r_majority, left, right, nums);
        return l_m_count>r_m_count?l_majority:r_majority;
    }

    private int getCount(int majority, int left, int right, int[] nums) {
        int count=0;
        for (int i=left;i<=right;i++){
            if (nums[i]==majority)count++;
        }
        return count;
    }

时间复杂度:On

空间复杂度:On

在这里插入图片描述

解法5:MorreVoting

/**
 * 思路:
 * 这个思路很巧妙,众数一定比其他数的总和多
 * 把第一个数记作众数,如果是第一个数count++,不是count--
 * 如果count==0说明这个数不是众数,把其他的数作为众数
 * 继续循环直到所有的数走完
 */
    public int majorityElement(int[] nums) {
        int count=0,majority=0;
        for (int num:nums){
            if (count==0)majority=num;
            if (num==majority)count++;
            else count--;
        }
        return majority;
    }

时间复杂度:On

空间复杂度:O1

在这里插入图片描述

解法6:map

/**
 * 思路:
 * map中k存数,v存次数
 * 遍历数组,不断的更新map,如果v>n/2返回
 */
    public int majorityElement(int[] nums) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num:nums){
            map.put(num,map.getOrDefault(num,0)+1);
            if(map.get(num)>nums.length/2)return num;
        }
        return -1;
    }

时间复杂度:On

空间复杂度:On

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值