leetcode 算法之多数元素

0 阅读5分钟

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

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

示例 1:

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

示例 2:

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

 

提示:

  • n == nums.length
  • 1 <= n <= 5 * 104
  • -109 <= nums[i] <= 109
  • 输入保证数组中一定有一个多数元素。

 

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

解题思路

我们需要循环遍历数组里面的元素然后去找到重复的元素并标记次数然后更新次数最大数,我们找到对应的元素 然后返回即可,这里需要理解题意 我们不是返回下标是返回元素的值。

  • 第一种方法 暴力枚举

我们通过2层for 循环去对比相邻的元素是否相等,如果相等我们才count 自增一下 然后我们的最大次数maxCount 和我们的count 比较去互换 最后把我们的currentElement 复制给我们 majorityElement 最后返回即可

public int majorityElement(int[] nums){
    // 边界检查
    if (nums == null || nums.length == 0) {
        return 0;
    }

    int maxCount = 0;
    int majorityElement = nums[0];
    // 对每个元素统计出现次数
    for (int i = 0; i < nums.length; i++) {
        int currentElement = nums[i];
        int count = 0;
        // 统计当前元素在整个数组中的出现次数
        for (int j = 0; j < nums.length; j++) {
            if (nums[j] == currentElement) {
                count++;
            }
        }
        // 更新最大出现次数和对应元素
        if (count > maxCount) {
            maxCount = count;
            majorityElement = currentElement;
        }
    }
    return majorityElement;
}

第一种方式看着代码比较好理解 但是他的时间复杂度是o(n平方的)并不是最优解,我们可以使用我们的map来处理使得我们的算法更简单

单元测试

public static void main(String[] args) {
    LeetCode5 solution = new LeetCode5();

    // 单元测试
    System.out.println("开始执行单元测试...");

    // 测试1: 正常情况
    int[] test1 = {1, 2, 3, 2, 2, 4, 2};
    int result1 = solution.majorityElement(test1);
    System.out.println("测试1 - 正常情况: " + result1 + " (期望: 2) " + (result1 == 2 ? "✓" : "✗"));

    // 测试2: 单个元素
    int[] test2 = {5};
    int result2 = solution.majorityElement(test2);
    System.out.println("测试2 - 单个元素: " + result2 + " (期望: 5) " + (result2 == 5 ? "✓" : "✗"));

    // 测试3: 所有元素相同
    int[] test3 = {3, 3, 3, 3, 3};
    int result3 = solution.majorityElement(test3);
    System.out.println("测试3 - 所有元素相同: " + result3 + " (期望: 3) " + (result3 == 3 ? "✓" : "✗"));

    // 测试4: 多个最大值元素
    int[] test4 = {1, 1, 2, 2, 3};
    int result4 = solution.majorityElement(test4);
    System.out.println("测试4 - 多个最大值: " + result4 + " (期望: 1或2) " +
            ((result4 == 1 || result4 == 2) ? "✓" : "✗"));

    // 测试5: null数组
    try {
        int result5 = solution.majorityElement(null);
        System.out.println("测试5 - null数组: " + result5 + " (期望: 0) " + (result5 == 0 ? "✓" : "✗"));
    } catch (Exception e) {
        System.out.println("测试5 - null数组: 异常捕获 " + e.getMessage() + " ✗");
    }

    // 测试6: 空数组
    int[] test6 = {};
    int result6 = solution.majorityElement(test6);
    System.out.println("测试6 - 空数组: " + result6 + " (期望: 0) " + (result6 == 0 ? "✓" : "✗"));

    // 测试7: 负数元素
    int[] test7 = {-1, -2, -1, -3, -1};
    int result7 = solution.majorityElement(test7);
    System.out.println("测试7 - 负数元素: " + result7 + " (期望: -1) " + (result7 == -1 ? "✓" : "✗"));

    // 测试8: 包含0的数组
    int[] test8 = {0, 1, 0, 2, 0, 3};
    int result8 = solution.majorityElement(test8);
    System.out.println("测试8 - 包含0: " + result8 + " (期望: 0) " + (result8 == 0 ? "✓" : "✗"));

    // 测试9: 大数组
    int[] test9 = new int[100];
    for (int i = 0; i < 60; i++) test9[i] = 7;
    for (int i = 60; i < 100; i++) test9[i] = i;
    int result9 = solution.majorityElement(test9);
    System.out.println("测试9 - 大数组: " + result9 + " (期望: 7) " + (result9 == 7 ? "✓" : "✗"));

    // 测试10: 首尾元素相同
    int[] test10 = {1, 2, 3, 4, 1};
    int result10 = solution.majorityElement(test10);
    System.out.println("测试10 - 首尾相同: " + result10 + " (期望: 1) " + (result10 == 1 ? "✓" : "✗"));

    System.out.println("单元测试执行完毕!");
}
  • 效果

image.png

  • 第二种发方式 使用map来枚举

public int majorityElement2(int[] nums){
    // 边界检查
    if (nums == null || nums.length == 0) {
        return 0;
    }
    // 使用HashMap统计每个元素出现次数
     Map<Integer, Integer> countMap = new HashMap<>();
    int maxCount = 0;
    int majorityElement2 = nums[0];

    // 遍历数组统计频次
    for (int num : nums) {
        int count = countMap.getOrDefault(num, 0) + 1;
        countMap.put(num, count);
        // 实时更新最高频次元素
        if (count > maxCount) {
            maxCount = count;
            majorityElement2 = num;
        }
    }
    return majorityElement2;
}

我们用map把我们的num 和count 存储起来 然后通过 countMap.getOrDefault(num, 0) 来查询我们的num 出现的次数最后再来更新我们的 maxCount即可。

单元测试

public static void main(String[] args) {
    LeetCode5 solution = new LeetCode5();

    // 单元测试
    System.out.println("开始执行单元测试...");

    // 测试1: 正常情况
    int[] test1 = {1, 2, 3, 2, 2, 4, 2};
    int result1 = solution.majorityElement2(test1);
    System.out.println("测试1 - 正常情况: " + result1 + " (期望: 2) " + (result1 == 2 ? "✓" : "✗"));

    // 测试2: 单个元素
    int[] test2 = {5};
    int result2 = solution.majorityElement2(test2);
    System.out.println("测试2 - 单个元素: " + result2 + " (期望: 5) " + (result2 == 5 ? "✓" : "✗"));

    // 测试3: 所有元素相同
    int[] test3 = {3, 3, 3, 3, 3};
    int result3 = solution.majorityElement2(test3);
    System.out.println("测试3 - 所有元素相同: " + result3 + " (期望: 3) " + (result3 == 3 ? "✓" : "✗"));

    // 测试4: 多个最大值元素
    int[] test4 = {1, 1, 2, 2, 3};
    int result4 = solution.majorityElement2(test4);
    System.out.println("测试4 - 多个最大值: " + result4 + " (期望: 1或2) " +
            ((result4 == 1 || result4 == 2) ? "✓" : "✗"));

    // 测试5: null数组
    try {
        int result5 = solution.majorityElement2(null);
        System.out.println("测试5 - null数组: " + result5 + " (期望: 0) " + (result5 == 0 ? "✓" : "✗"));
    } catch (Exception e) {
        System.out.println("测试5 - null数组: 异常捕获 " + e.getMessage() + " ✗");
    }

    // 测试6: 空数组
    int[] test6 = {};
    int result6 = solution.majorityElement2(test6);
    System.out.println("测试6 - 空数组: " + result6 + " (期望: 0) " + (result6 == 0 ? "✓" : "✗"));

    // 测试7: 负数元素
    int[] test7 = {-1, -2, -1, -3, -1};
    int result7 = solution.majorityElement2(test7);
    System.out.println("测试7 - 负数元素: " + result7 + " (期望: -1) " + (result7 == -1 ? "✓" : "✗"));

    // 测试8: 包含0的数组
    int[] test8 = {0, 1, 0, 2, 0, 3};
    int result8 = solution.majorityElement2(test8);
    System.out.println("测试8 - 包含0: " + result8 + " (期望: 0) " + (result8 == 0 ? "✓" : "✗"));

    // 测试9: 大数组
    int[] test9 = new int[100];
    for (int i = 0; i < 60; i++) test9[i] = 7;
    for (int i = 60; i < 100; i++) test9[i] = i;
    int result9 = solution.majorityElement2(test9);
    System.out.println("测试9 - 大数组: " + result9 + " (期望: 7) " + (result9 == 7 ? "✓" : "✗"));

    // 测试10: 首尾元素相同
    int[] test10 = {1, 2, 3, 4, 1};
    int result10 = solution.majorityElement2(test10);
    System.out.println("测试10 - 首尾相同: " + result10 + " (期望: 1) " + (result10 == 1 ? "✓" : "✗"));

    System.out.println("单元测试执行完毕!");
}
  • 测试结果

image.png