面试题 17.10. 主要元素——数组

面试题 17.10. 主要元素

题目描述

数组中占比超过一半的元素称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-1。

示例 1:

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

示例 2:

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

示例 3:

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

解题思路

以下涉及好几种方法,推荐使用排序后验证中间元素


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

//leetcode submit region begin(Prohibit modification and deletion)
class Solution_17_10 {
    
    
    public int majorityElement_1(int[] nums) {
    
    
        /**
         * 哈希表 ,时间复杂度 O(N2),空间复杂度O(N)
         */
        HashMap<Integer,Integer> map = new HashMap<>();
        int p = nums.length / 2;
        for (int i = 0; i < nums.length; i++) {
    
    
            map.put(nums[i],map.getOrDefault(nums[i],0) + 1);
        }
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    
    
            if(entry.getValue() > p){
    
    
                return entry.getKey();
            }
        }
        return -1;
    }

    /**
     * 排序后,使用双指针,统计大于超过一半长度的元素
     * @param nums
     * @return
     */
    public int majorityElement_2(int[] nums) {
    
    
        if (nums.length == 1){
    
    
            return nums[0];
        }

        Arrays.sort(nums);
        System.out.println(Arrays.toString(nums));
        int start = 0;
        int end = 0;
        for (int i = 1; i < nums.length; i++) {
    
    
            if (nums[i - 1] == nums[i]){
    
    
                end++;
            }else {
    
    
                start = end + 1;
                end++;
            }
            if (end - start + 1 > nums.length / 2){
    
    
                return nums[start];
            }
        }
        return -1;
    }

    /**
     * 排序后验证中间元素
     * @param nums
     * @return
     */
    public int majorityElement_3(int[] nums) {
    
    
        Arrays.sort(nums);
        int ans = nums[nums.length / 2];
        int number = 0;
        for (int num : nums) {
    
    
            if (num == ans){
    
    
                number++;
            }
        }
        if (number > nums.length / 2){
    
    
            return ans;
        }
        return -1;
    }

    /**
     * 首先给这个数组排序,然后如果有主要元素,那么这个元素一定在中间,
     * 可以定义两个指针,从这个数的左右开始扫描,扫描到一个相同的数。
     * 令左指针减一或右指针加一,当扫描完成后,令右指针-左指针-2+1,
     * 由于一开始两个指针相差2,所以要减去2,这样的话就算得了扫描的个数,
     * 但是还有中间的那个数没有算,所以需要加一,最后判断这个算得的数是否大于数组的一半即可
     * 时间复杂度:排序的时候是快排O(n*logn)+O(n)+O(n),空间为O(1)
     *
     */

    public int majorityElement(int[] nums) {
    
    

        Arrays.sort(nums);

        int left = nums.length/2-1, right = nums.length/2+1, num = nums[nums.length/2];

        while (left >= 0 && nums[left] == num) {
    
    
            left --;
        }

        while (right < nums.length && nums[right] == num) {
    
    
            right ++;
        }
        if (right - left - 1> nums.length/2) {
    
    
            return num;
        }
        return -1;
    }

    /**
     * 摩尔投票法
     * @param nums
     * @return
     */
    public int majorityElement_4(int[] nums) {
    
    
        int temp = 0,count = 0;
        for (int num : nums) {
    
    
            if (count == 0){
    
    
                temp = num;
                count = 1;
            }
            else {
    
    
                if (temp == num){
    
    
                    count++;
                }else {
    
    
                    count--;
                }
            }
        }
        if (count > 0){
    
    
            int n = 0;
            for (int i : nums) {
    
    
                if (i == temp)
                    n++;
            }
            if (n > nums.length / 2){
    
    
                return temp;
            }

        }
        return -1;
    }

}
//leetcode submit region end(Prohibit modification and deletion)

猜你喜欢

转载自blog.csdn.net/qq_35655602/article/details/115256313