iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
自我挑戰組

Leetcode刷題筆記系列 第 14

[Day 14] Leetcode 115. Distinct Subsequences (C++)

  • 分享至 

  • xImage
  •  

前言

今日挑戰的題目是115. Distinct Subsequences,雖然是hard,但因為有點想法,感覺可以挑戰一下XD 就一起來破解這題難題吧!

想法

首先想法是,要在不破壞順序的情形下,可以隨意刪除字元,讓剩下的字元可以組成target字串。這樣的話,就又是dp出場的時候了,因為這可以拆成比較簡單的子問題形式。我們可以用dp來存s中每個位置的可能答案總數,為了單純化,我們可以先假設t只有一個字元,那這問題是不是就變得很簡單?從s[0]開始看,如果s[0]==t,那dp[0]就=1,如果走到第二格發現s[1]也==t,那我們就知道有兩個可能,所以就dp[1]=dp[0]+1=2,如果走到s的第三格發現s[2]!=t,那仍然只有兩個可能,dp[2]=dp[1]+0=2。
現在我們進一步考慮t不只一個字元的情形,我們就讓dp變成二維的,dp[i][j]代表在s[:i]的字串中,可以有多少t[:j]的可能組合;更新的方式就會變成dp[i][j]=dp[i-1][j] + s[i]==t[j]?dp[i-1][j-1]:0;為什麼?如果不相等的話很簡單,就=隔壁的情形;那如果相等的話就會有更多可能的結果,那會多多少組合?你可以試著列列看簡單的範例,重點就是要多多少排列組合。
寫成程式如下:

class Solution {
public:
    int numDistinct(string s, string t) {
        
        // use dp to save the possibilities
        int sl = s.length();
        int tl = t.length();
        vector<vector<unsigned long long>> cnt (sl, vector<unsigned long long>(tl,0));
        //vector<vector<long long>> cnt (sl, vector<long long>(tl,0));

        // for the first word in t
        cnt[0][0] = (s[0]==t[0])?1:0;
        for(int i=1;i<sl;++i){
            cnt[i][0] = cnt[i-1][0] + (s[i]==t[0]);
        }
        // for other rounds
        for(int i=1;i<sl;++i){
            for(int j=1;j<tl;++j){
                cnt[i][j] = cnt[i-1][j] + (s[i]==t[j])*cnt[i-1][j-1];
            }
        }
        return cnt[sl-1][tl-1];
        
    }
};

還有中間的坑是test case讓answer變成超大的數,要unsigned long long才存得下...若要查詢每個型別的容納數範圍可以參考這邊

結語

雖然是hard但其實dp類型問題就是一旦掌握到更新的方式,就可以做出來了。接下來也可以再多多挑戰這類的題目~
而這題也跟其他dp一樣,也有辦法優化空間複雜度從O(m*n)變成O(n),只要考慮到前一行的情形就好。


上一篇
[Day 13] Leetcode 49. Group Anagrams (C++)
下一篇
[Day 15] Leetcode 138. Copy List with Random Pointer (C++)
系列文
Leetcode刷題筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言