[剑指-Offer] 39. 数组中出现次数超过一半的数字(多数投票算法、sort函数、代码优化)

1. 题目来源

链接:数组中出现次数超过一半的数字
来源:LeetCode——《剑指-Offer》专项

2. 题目说明

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

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

示例 1:

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

限制:

  • 1 <= 数组长度 <= 50000

3. 题目解析

方法一:多数投票算法+ O ( n ) O(n) O(n)时间复杂度+最优解法

算法思想相当简单,即不同的数两两抵消,超过一半的数字是抵消后剩余的数字,关于这个算法的详细介绍以及相关 OJ 这是博主的总结链接:[杂谈] 7. Majority Vote Algorithm 多数投票算法

参见代码如下:

// 执行用时 :20 ms, 在所有 C++ 提交中击败了82.68%的用户
// 内存消耗 :21.7 MB, 在所有 C++ 提交中击败了100.00%的用户

class Solution {
public:
    int majorityElement(vector<int> numbers) {
        int num = 0, count = 0;
        for (int i = 0; i < numbers.size(); i++) {
            if (count == 0) num = numbers[i];
            if (numbers[i] == num) count++;
            else count--;
        }
        return num;
    }
};

稍作改动并验证正确性版本:

// 执行用时 :20 ms, 在所有 C++ 提交中击败了82.68%的用户
// 内存消耗 :21.8 MB, 在所有 C++ 提交中击败了100.00%的用户

class Solution {
public:
    int majorityElement(vector<int> numbers) {
        int n = numbers.size();
        if (n == 0) 
            return 0;
        int num = numbers[0], count = 1;
        for (int i = 1; i < n; i++) {
            if (numbers[i] == num) 
                count++;
            else 
                count--;
            if (count == 0) {
                num = numbers[i];
                count = 1;
            }
        }
        // 经过上面的操作, 已经找到该数 num 了. 
        // 下面的操作是为了确认 num 确实是出现次数超过一半. 
        count = 0;
        for (int i = 0; i < n; i++) {
            if (numbers[i] == num) 
                count++;
        }
        if (count * 2 > n) 
            return num;
        return 0;
    }
};

方法二:sort()排序+ O ( l o g n ) O(logn) O(logn)时间复杂度+投机解法

sort() 排序最中间的数字肯定是超过一半的数字,但是 sort() 时间复杂度为 O ( l o g n ) O(logn) O(logn) 颇高。

参见代码如下:

// 执行用时 :24 ms, 在所有 C++ 提交中击败了62.85%的用户
// 内存消耗 :21.3 MB, 在所有 C++ 提交中击败了100.00%的用户

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        return nums[nums.size() >> 1];
    }
};
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值