置頂

我的 VPython 教學文件 (HackMD 版本)

VPython 教學文件目錄 安裝及測試 基本語法 等速度直線運動 自由落下 終端速度 水平抛射 使用For迴圈計算水平抛射資料 斜向抛射 圓周運動 簡諧運動 單擺 木塊彈簧系統分離 重力及簡諧 行星運動 相疊木塊 雙重簡諧運動 一維彈性碰撞 ...

熱門文章

2026年9月7日 星期一

LeetCode 解題筆記:940. Distinct Subsequences II

作者:王一哲
日期:2026年9月7日


LeetCode 題目連結:940. Distinct Subsequences II

解題想法


困難題。題目給一個字串 $s$,要找出 $s$ 可以組合成幾個不重複的子字串,由於答案可能很大,要對 $10^9 + 7$ 取餘數。這題要用動態規畫解題,定義一個長度為 $26$ 的陣列 $dp$,$dp[i]$ 代表以第 $i$ 個字母結尾的子字串數量,依序從 $s$ 讀取字母 $c$,先取 $c$ 的索引值 $idx = ord(c) - ord('a')$,可以將 $c$ 接在原有的子字串後面或是自己獨立成新的子字串,因此更新方式為 $$ newdp[idx] = \left ( \sum_{i = 0}^{25} dp[i] \right ) + 1 \pmod{MOD} $$ 但是這樣的寫法每次更新時都要重新計算 $dp$ 的加總,速度不快。另外定義一個變數 $total$ 用來記錄 $dp$ 的加總,每次更新 $dp[idx]$ 時將 $dp[idx]$ 的值存到另一個變數 $prev$,更新方式改為 $$ dp[idx] = (total + 1) \pmod{MOD} $$ 接下來更新 $total$ $$ total = (total + dp[idx] - prev) \pmod{MOD} $$ 如果用 C 或 C++ 解題,為了避免在上一行相加時溢位以及相減時變成負數,要改成 $$ total = ((total + dp[idx]) \pmod{MOD} - prev + MOD) \pmod{MOD} $$

Python 程式碼


Runtime: 7 ms, beats 89.58%. Memory: 19.32 MB, beats 46.35%.
class Solution:
    def distinctSubseqII(self, s: str) -> int:
        MOD = 10**9 + 7
        dp = [0] * 26  # 以各個小寫字母結尾的子字串數量
        total = 0  # 目前的子字串數量
        for c in s:  # 依序讀取字母
            idx = ord(c) - ord('a')  # 轉成 dp 串列索引值
            prev = dp[idx]  # 檢查到前一個字母時的值
            dp[idx] = (total + 1) % MOD  # 可以接在之前的子字串後面,或是自己獨立成新的子字串
            total = (total + dp[idx] - prev) % MOD  # 更新 total
        return total


C++ 程式碼


Runtime: 0 ms, beats 100.00%. Memory: 8.95 MB, beats 62.00%.
class Solution {
public:
    int distinctSubseqII(string s) {
        const int MOD = 1000000007;
        vector<int> dp (26, 0);
        int total = 0;
        for(char c : s) {
            int idx = c - 'a';
            int prev = dp[idx];
            dp[idx] = (total + 1) % MOD;
            total = ((total + dp[idx]) % MOD - prev % MOD + MOD) % MOD;
        }
        return total;
    }
};


C 語言程式碼


Runtime: 3 ms, beats -%. Memory: 8.80 MB, beats 66.67%.
int distinctSubseqII(char* s) {
    const int MOD = 1000000007;
    int dp[26] = {0}, total = 0, n = strlen(s);
    for(int i = 0; i < n; i++) {
        int idx = s[i] - 'a';
        int prev = dp[idx];
        dp[idx] = (total + 1) % MOD;
        total = ((total + dp[idx]) % MOD - prev + MOD) % MOD;
    }
    return total;
}


沒有留言:

張貼留言