Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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;
        
    }
}