2327.知道秘密的人数

目标

在第 1 天,有一个人发现了一个秘密。

给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后,每天 给一个新的人 分享 秘密。同时给你一个整数 forget ,表示每个人在发现秘密 forget 天之后会 忘记 这个秘密。一个人 不能 在忘记秘密那一天及之后的日子里分享秘密。

给你一个整数 n ,请你返回在第 n 天结束时,知道秘密的人数。由于答案可能会很大,请你将结果对 10^9 + 7 取余 后返回。

示例 1:

输入:n = 6, delay = 2, forget = 4
输出:5
解释:
第 1 天:假设第一个人叫 A 。(一个人知道秘密)
第 2 天:A 是唯一一个知道秘密的人。(一个人知道秘密)
第 3 天:A 把秘密分享给 B 。(两个人知道秘密)
第 4 天:A 把秘密分享给一个新的人 C 。(三个人知道秘密)
第 5 天:A 忘记了秘密,B 把秘密分享给一个新的人 D 。(三个人知道秘密)
第 6 天:B 把秘密分享给 E,C 把秘密分享给 F 。(五个人知道秘密)

示例 2:

输入:n = 4, delay = 1, forget = 3
输出:6
解释:
第 1 天:第一个知道秘密的人为 A 。(一个人知道秘密)
第 2 天:A 把秘密分享给 B 。(两个人知道秘密)
第 3 天:A 和 B 把秘密分享给 2 个新的人 C 和 D 。(四个人知道秘密)
第 4 天:A 忘记了秘密,B、C、D 分别分享给 3 个新的人。(六个人知道秘密)

说明:

  • 2 <= n <= 1000
  • 1 <= delay < forget <= n

思路

在第 1 天有一个人发现了一个秘密,每一个新知道秘密的人在 delay 天之后的 每一天 会向一个 新人 分享这个秘密,每一个人在知道秘密之后的 forget 天会忘记秘密,求第 n 天结束时知道秘密的人数。

定义 dp[i] 表示在第 i新增 知道秘密的人数,它等于超过了延迟 delay 并且还没有忘记的人数总和,也即 [i - forget + 1, i - delay] 之间的新增人数总和,求和可以使用前缀和优化。

代码


/**
 * @date 2025-09-09 8:57
 */
public class PeopleAwareOfSecret2327 {

    public int peopleAwareOfSecret(int n, int delay, int forget) {
        int[] dp = new int[n + 1];
        int mod = 1000000007;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            for (int j = Math.max(0, i - forget + 1); j <= Math.max(0, i - delay); j++) {
                dp[i] = (dp[i] + dp[j]) % mod;
            }
        }
        int res = 0;
        for (int i = Math.max(0, n - forget + 1); i <= n; i++) {
            res = (res + dp[i]) % mod;
        }
        return res;
    }

}

性能

3174.清除数字 – 双端队列

目标

给你一个字符串 s 。

你的任务是重复以下操作删除 所有 数字字符:

  • 删除 第一个数字字符 以及它左边 最近 的 非数字 字符。

请你返回删除所有数字字符以后剩下的字符串。

示例 1:

输入:s = "abc"
输出:"abc"
解释:
字符串中没有数字。

示例 2:

输入:s = "cb34"
输出:""
解释:
一开始,我们对 s[2] 执行操作,s 变为 "c4" 。
然后对 s[1] 执行操作,s 变为 "" 。

说明:

  • 1 <= s.length <= 100
  • s 只包含小写英文字母和数字字符。
  • 输入保证所有数字都可以按以上操作被删除。

思路

删除给定字符串中的数字字符,每次删除操作需要同步删除该字符左侧最后一个非数字字符。

遍历的过程中使用栈保存非数字字符,遇到数字字符就弹栈,然后返回栈底到栈顶的字符即可。

知识点:

  • ArrayDeque 双端队列的特性取决于如何放入数据

                    start
             last           first
    offer       4 3 2 1
    push              1 2 3 4
  • offer是向左添加数据

  • push是向右添加数据

  • poll/pop/remove 默认从右向左取数据

  • 如果api中带last,例如pollLast、removeLast则是从左向右取,first则相反

代码


/**
 * @date 2024-09-05 8:47
 */
public class ClearDigits3174 {

    public String clearDigits(String s) {
        int n = s.length();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            if (c > '9' || c < '0') {
                sb.append(c);
            } else {
                sb.deleteCharAt(sb.length() - 1);
            }
        }
        return sb.toString();
    }

}

性能