多数元素

目录

一、 需求     

 二、暴力匹配法

2.1  思路分析       

2.2  代码实现

2.3  复杂度分析

三、HashMap实现

3.1  思路分析

3.2  代码实现

3.3  复杂度分析

四、排序法

4.1  思路分析

4.2  代码实现

4.3  复杂度分析

五、随机法

5.1  思路分析    

5.2  代码实现

5.3  复杂度分析

六、分治算法

6.1  思路分析

6.2  代码实现

6.3  复杂度分析

七、摩尔投票法

7.1  思路分析

7.2  代码实现

7.3  复杂度分析

八、位运算

8.1  思路分析

8.2  代码实现

8.3  复杂度分析

九、参考地址


一、需求     

      A:给定一个大小为n的数组,找到其中的多数元素;

         a:多数元素是指在数组中出现次数大于[n/2]的元素;

      B:假设数组非空,并且给定的数组总是存在多数元素;

 二、暴力匹配法

2.1  思路分析       

      A:遍历数组,依次计算每个元素在数组中出现的次数;

      B:若次数大于n/2,则返回该元素;

      C:因为题目假定数组中含有多数元素,故最后的返回值随便返回一个数据就行;

2.2  代码实现

public int majorityElement(int[] nums) {
        for(int i = 0; i < nums.length; i++) {
            int count = 0;
            for(int j = 0; j < nums.length; j++) {
                if(nums[i] == nums[j]) {
                    count++;
                } 
            }
            if(count > nums.length/2) {
                return nums[i];
            }
        }
        return -1;
    }

2.3  复杂度分析

      A:时间复杂度为O(n^2);

      B:空间复杂度为O(1);

三、HashMap实现

3.1  思路分析

      A:创建HashMap对象,键表示数组值,值表示相同数组值的个数;

      B:遍历数组,如果HashMap中不存在该数值,则将该数值加入HashMap中,对应的值为1;

      C:如果HashMap中存在该数值,那该数值键对应的值加一;

      D:等到当前键对应的值满足条件时,直接退出循环,经测试再加一个判断即可;

      E:当然,也可以在遍历完数组后,开始遍历HashMap的键,得到每一个值,若该值大于n/2,则直接返回该键;

3.2  代码实现

public int majorityElement(int[] nums) {
        //创建对象
        HashMap<Integer,Integer> hm = new HashMap<Integer,Integer>();
        //特殊情况
        if(nums.length == 1) {
            return nums[0];
        }
        //遍历数组
        for(int i = 0; i < nums.length; i++) {
            if(hm.containsKey(nums[i])) {
                //map中直接修改键值,要重新覆盖
                hm.put(nums[i],hm.get(nums[i])+1); 
                int count = hm.get(nums[i]);
                if(count > nums.length/2) {
                    return nums[i];
                }      
            } else {
                hm.put(nums[i],1);
            }
        }
        return -1;
    }

3.3  复杂度分析

      A:时间复杂度为O(n);

      B:空间复杂度为O(n);

四、排序法

4.1  思路分析

      A:将数组中的元素进行排序,多数元素个数必然大于n/2,所以直接返回中间的元素即可;

4.2  代码实现

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

4.3  复杂度分析

      A:时间复杂度为O(nlogn);

      B:空间复杂度为O(n)或者O(1),分别对应线性空间中拷贝数组排序和就地排序;

五、随机法

5.1  思路分析    

      A:创建Random对象,随机获取数组中的一个数据;

      B:然后遍历数组,判断这个数据出现的次数是否大于n/2;

      C:大于则返回该数据,否则继续循环;

5.2  代码实现

public int majorityElement(int[] nums) {
        //创建Random对象
        Random rand = new Random();
        while(true) {
            //随机获取数组的某一下标
            int index = rand.nextInt(nums.length);
            int count = 0;
            //遍历数组
            for(int i = 0; i < nums.length; i++) {
                if(nums[i] == nums[index]) {
                    count++;
                }
            }
            if(count > nums.length/2) {
                return nums[index];
            }
        }
}

5.3  复杂度分析

      A:时间复杂度理论上来说是O(∞),但是众数占据了一半以上,迭代的期望次数是个常数,期望运行的时间也是线性的;

      B:空间复杂度为O(1);

六、分治算法

6.1  思路分析

6.2  代码实现

class Solution {
    //创建计算元素个数的功能
    private int number(int[] nums,int num,int left_index,int right_index) {
        int count = 0;
        for(int i = left_index; i <= right_index; i++) {
            if(nums[i] == num) {
                count++;
            }
        }
        return count;
    }
    //递归函数
    private int diGui(int[] nums,int left_index,int right_index) {
        //递归结束条件
        if(left_index == right_index) {
            return nums[left_index];
        }
        //开始拆分数组为左子数组和右子数组
        int mid = (left_index + right_index) >>> 1;
        //定义左子数组众数left
        int left = diGui(nums,left_index,mid);    
        //定义右子数组众数right
        int right = diGui(nums,mid+1,right_index);
        //左右众数相同
        if(left ==  right) {
            return left;
        }
        //左右众数不同
        int left_Count = number(nums,left,left_index,right_index);
        int right_Count = number(nums,right,left_index,right_index);

        return left_Count > right_Count ? left:right;
    }

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

6.3  复杂度分析

      A:时间复杂度O(nlogn);

      B:空间复杂度O(logn);

七、摩尔投票法

7.1  思路分析

      A:假设众数用+1来表示,非众数用-1来表示,所有数据加起来的结果必然大于0;

      B:遍历数组,假定第一个数就是众数,则count+1,也就是有一个+1了;

      C:然后继续遍历,若与当前众数相同,那么count+1,若不同,则count-1;

      D:当count==0时,继续计算下一个众数的count,一定会有count>0,这时候返回当前的众数;

7.2  代码实现

public int majorityElement(int[] nums) {
        int current_mode = 0;
        int count = 0;
        //遍历数组
        for(int num : nums) {
            if(count == 0) {
                current_mode = num;
            }
            count += current_mode == num ? 1 : -1;
        }
    return current_mode;
}

7.3  复杂度分析

      A:时间复杂度为O(n);

      B:空间复杂度为O(1);

八、位运算

8.1  思路分析

8.2  代码实现

public int majorityElement(int[] nums) {
        int majority = 0; 
        int n = nums.length;
        //遍历32列
        for(int i = 0, mask = 1; i < 32; i++, mask <<= 1) {
            int count = 0;
            for(int j = 0; j < n; j++) {
                if((mask & nums[j]) == mask) {
                    count++;
                }
            }
            if(count > n/2) {
                majority |= mask;
            }
        }
    return majority;
}

8.3  复杂度分析

      A:时间复杂度为O(32n),也就是O(n);

      B:空间复杂度为O(1);

九、参考地址

      A:https://leetcode-cn.com/problems/majority-element/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-4-2/

      B:https://leetcode-cn.com/problems/majority-element/solution/qiu-zhong-shu-by-leetcode-2/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值