Leetcode 2327. Number of People Aware of a Secret
Woodyiiiiiii opened this issue · comments
这道题我一开始想的是尽量分开使用delay和forget两个参数,所以将forget放到最后计算。dp[i]表示第i天刚知道secret的人数。时间复杂度是O(n*2)。
class Solution {
public int peopleAwareOfSecret(int n, int delay, int forget) {
long mod = 1000000007;
long[] dp = new long[n + 1];
dp[1] = 1;
for (int i = 1; i < n; ++i) {
for (int j = i + delay; j < i + forget && j <= n; ++j) {
dp[j] = (dp[j] + dp[i]) % mod;
}
}
long res = 0;
for (int i = n; i > n - forget; --i) {
res = (res + dp[i]) % mod;
}
return (int) res;
}
}
一位朋友使用O(n)的时间复杂度可以做出。但问题是,因为每个计算过程都要mod,遇到减法时就会出错,比如5-1=4, 5%2-1=0,而最后再用mod使用long类型可能会溢出。所以使用BigInteger可以防止溢出。时间复杂度为O(n)。
dp[i]表示第i天及之前知道secret的人数。所以最后要减去forget secret的人数。
import java.math.BigInteger;
class Solution {
public int peopleAwareOfSecret(int n, int delay, int forget) {
BigInteger[] dp = new BigInteger[n + 1];
BigInteger mod = BigInteger.valueOf(1000000007);
dp[0] = BigInteger.valueOf(0);
dp[1] = BigInteger.valueOf(1);
for (int i = 2; i <= n; i++) {
BigInteger sum = BigInteger.valueOf(0);
if (i - delay >= 0) {
sum = sum.add(dp[i - delay]);
}
if (i - forget >= 0) {
sum = sum.subtract(dp[i - forget]);
}
dp[i] = dp[i - 1].add(sum).mod(mod);
}
return dp[n].subtract(dp[n - forget]).mod(mod).intValue();
}
}
为了避免上述说的减法取余的情况,加上一个mod即可。其余做法跟上述算法相同。
稍微不同的是,share一开始为0。dp[i]表示的是第i天净知道secret的人数。所以最后要相加。
class Solution {
public int peopleAwareOfSecret(int n, int delay, int forget) {
long dp[] = new long[n + 1];
long mod = (long)1e9 + 7;
long share = 0;
long res = 0;
dp[1] = 1;
for (int i = 2; i <= n; ++i) {
dp[i] = share = (share + dp[Math.max(i - delay, 0)] - dp[Math.max(i - forget, 0)] + mod) % mod;
}
for (int i = n - forget + 1; i <= n; ++i) {
res = (res + dp[i]) % mod;
}
return (int)res;
}
}