知道秘密的人数[对刷算法的理解]

前言

刷算法题(中等题以上)有两种境界,第一种就是秒算法题,这需要大量的知识积累,以及快速抓住核心问题并理解的能力;第二种是基本能力,就是需要做到见招拆招,大多数招是隐式的,所以需要通过认真分析才能看到背后的招式,利用自己积累的知识灵活解题。

一、知道秘密的人数

在这里插入图片描述

二、问题分析+时间流逝问题

package competition.single300;

import java.util.LinkedList;
import java.util.List;

public class PeopleAwareOfSecret {
    /*
    每个人每天能否传播,要看当天是不是在delay之后,forget之前,即[delay,forget)。
    比如第i天,A知道了密码,设置delay = i + delay;forget = i + forget.
    现在第j天,A能否传播秘密,当j >= delay && j < forget;
    每一天传播的人为一组,他们有相同的delay和forget;前后两组的delay和forget都相差1.

    每传播一次,就加一次知道秘密的人数。
     */
    // 采用一次索引形式,减轻取余数的复杂书写。
    final static int mod = (int) 1e9 + 7;

    public int peopleAwareOfSecret(int n, int delay, int forget) {
        List<int[]> que = new LinkedList<>();
        // 第1天,该组只有一个人知到秘密,且它将来可以传播秘密。
        // que的size维持在forget大小,毕竟过了就忘了,在这期间,大于等于delay后的才能传播秘密。
        que.add(new int[]{1, 1 + delay, 1 + forget});// 第1天为第1天时知道秘密。
        int ans = 1;
        for (int i = 2; i <= n; i++) {
            // 将忘记秘密的一组人移除队列。
            while (!que.isEmpty() && que.get(0)[2] <= i) {
                // 知道秘密的人流失。
                ans -= que.get(0)[0];
                ans = (ans + mod) % mod;
                // 他已经不能传播秘密了。
                que.remove(0);
            }
            // 取今天能传播多少人,并将其加到ans中。
            int spreed = 0;
            for (int j = 0; j < que.size(); j++) {
                if (i >= que.get(j)[1]) {
                    spreed += que.get(j)[0];
                    spreed %= mod;
                }
            }
            // 得到传播总人数,不断累计。
            ans = (ans + spreed) % mod;
            // 并将其加入队列。
            que.add(new int[]{spreed, i + delay, i + forget});
        }
        return ans;//5 2 3
    }

    public static void main(String[] args) {
        new PeopleAwareOfSecret().peopleAwareOfSecret(4, 1, 3);
    }
}

总结

1)分析问题 -> 找到核心问题 -> 联系已有知识灵活应用。
2)平时负重前行,周赛才有可能灵活分析与应用知识点,取其上着得其中,多实践找找差距。
3)题目说取余,我一贯以为是最后结果很大,int存不下,所以需要最后取余,结果一直通不过。题意是中间每个结果都需要取余,否则会溢出。所以平时题感/经验刷少了。

参考文献

[1] LeetCode 第300单周赛 知道秘密的人数

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值