2-微信红包(2016腾讯校招)

文章介绍了一种高效的算法,用于在红包金额数组中找到出现次数超过总数一半的金额。通过遍历数组,使用计数和抵消的方法,在O(n)的时间复杂度和O(1)的空间复杂度下解决问题。如果不存在这样的金额,则返回0。

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

题目

春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。

给定一个红包的金额数组gifts及它的大小n,请返回所求红包的金额。

若没有金额超过总数的一半,返回0。

数据范围:1 <= n <= 1000,红包金额满足1 <= gifti <= 100000。

示例1

输入 [1,2,3,2,2],5

输出 2

示例2

输入 [1,1,2,2,3,3],6

输出 0


思路

↑最简单思路:

分别算出每个红包金额出现次数,再找出出现次数过半的金额。

↑进阶思路:

考虑到时间/空间复杂度,是否可以优化为时间复杂度O(n),空间复杂度O(1)呢?那就是只在原数组遍历一次而不申请其他数组。

挖掘题目所给的重要信息:红包金额出现次数超过“一半”(而不是1/3或1/4),so求解方法与“一半”有关。是否只用求出该红包金额,而不用算出该红包出现次数呢~可以!在求解时次数可以加以利用并改变。

so~遍历原数组,只要是两个不同的金额,就直接抵消掉,最后剩哪个就是哪个过半。

具体解法:计数+验证

  • 让key最初暂为数组第一个元素,而后在数组遍历中不断更新,用来保存最终的候选值。
  • count最初是1,用来计数。
  • 遍历数组(从数组第二个元素开始遍历)
  1. 若当前所遍历的数组元素值与当前key值相等,则count+1。
  2. 若当前所遍历的数组元素值与当前key值不等,则count-1。
  3. 若count为0,说明互相抵消完,前一个候选的值不是超过一半的数,则更新候选值,改变key值为此时遍历的数组下标所对应的数组元素值,还原count为1。
  • 判断key出现的次数是否大于数组长度的一半,若大于,则return key;否则,return 0。

代码

public class WeChatRedEnvelope {
    public int weChatRedEnvelope(int[] gifts, int n) {
        //遍历原数组,只要是两个不同的金额,就直接抵消掉,最后剩哪个就是哪个过半
        int key = gifts[0];
        int count = 1;
        for (int i = 1; i < n; i++) {
            if(gifts[i] == key) {
                count++;
            } else {
                count--;
            }
            if(count == 0) {
                key = gifts[i];
                count = 1;
            }
        }

        //判断key出现的次数是否大于数组长度的一半
        int num = 0;
        for (int i = 0; i < n; i++) {
            if(gifts[i] == key) {
                num++;
            }
        }
        //此时num为key重复的次数
        if(num > (n / 2)) {
            return key;
        } else {
            return 0;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值