13.数组中出现次数超过一半的数字

本文介绍两种算法,用于找出数组中出现次数超过一半的数字。第一种算法利用O(n)时间复杂度,通过比较相邻元素并计数来找到多数元素。第二种算法使用C++的快速排序,选取中位数作为可能的多数元素,再验证其是否符合条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

解法1:

需要O(n)时间,(剑指解法2)

1)它比较的是两两相临近的的数组是否相等,相等则计数1,同时参与比较的这个数num保持不变参与下一次的比较;

2)否则计数为0时,num重新取值;因为条件是:出现的次数大于数组长度的一半,为此肯定会出现相邻两个数重复的情况;

3)最后只要判断最后num的数值就是出现的次数大于数组长度的一半的数;

考虑的特殊条件是:数组长度为0;或者出现的次数小于数组长度的一半

class Solution {
 public:
    int MoreThanHalfNum_Solution(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;
            }
        }
        // 判断是否有效,满足出现的次数超过数组的一半吗
        count = 0;
        for (int i = 0; i < n; i++) 
        {
            if (numbers[i] == num) count++;
        }
        if (count * 2 > n) return num;
        return 0;
    }
};

解法2:C++自带的快速排序,并取中间的值作为结果

// 该方法取排序数组中间的值,即是该数字出现的次数超过数组长度的一半,也称为中位数
class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers)
    {
        // 因为用到了sort,时间复杂度O(NlogN),并非最优
        if(numbers.empty()) return 0;
         // C++ 内的sort默认为快排参考 https://www.cnblogs.com/jjzzx/p/5122381.html
        sort(numbers.begin(),numbers.end()); // 排序,取数组中间那个数,默认为从小到大排序
        int middle = numbers[numbers.size()/2];
         
        int count=0; // 出现次数
        for(int i=0;i<numbers.size();++i)
        {
            if(numbers[i]==middle) ++count;
        }
         
        return (count>numbers.size()/2) ? middle :  0;
    }
};

参考:https://www.nowcoder.com/profile/6081968/codeBookDetail?submissionId=15299432

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

heda3

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值