C++實(shí)現(xiàn)LeetCode(115.不同的子序列)
[LeetCode] 115. Distinct Subsequences 不同的子序列
Given a string S and a string T, count the number of distinct subsequences of S which equals T.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).
Example 1:
Input: S =
"rabbbit"
, T =
"rabbit"
Output: 3
Explanation:
As shown below, there are 3 ways you can generate "rabbit" from S.
(The caret symbol ^ means the chosen letters)
rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^
Example 2:
Input: S =
"babgbag"
, T =
"bag"
Output: 5
Explanation:
As shown below, there are 5 ways you can generate "bag" from S.
(The caret symbol ^ means the chosen letters)
babgbag
^^ ^
babgbag
^^ ^
babgbag
^ ^^
babgbag
^ ^^
babgbag
^^^
看到有關(guān)字符串的子序列或者配準(zhǔn)類的問題,首先應(yīng)該考慮的就是用動(dòng)態(tài)規(guī)劃 Dynamic Programming 來求解,這個(gè)應(yīng)成為條件反射。而所有 DP 問題的核心就是找出狀態(tài)轉(zhuǎn)移方程,想這道題就是遞推一個(gè)二維的 dp 數(shù)組,其中 dp[i][j] 表示s中范圍是 [0, i] 的子串中能組成t中范圍是 [0, j] 的子串的子序列的個(gè)數(shù)。下面我們從題目中給的例子來分析,這個(gè)二維 dp 數(shù)組應(yīng)為:
Ø r a b b b i t
Ø 1 1 1 1 1 1 1 1
r 0 1 1 1 1 1 1 1
a 0 0 1 1 1 1 1 1
b 0 0 0 1 2 3 3 3
b 0 0 0 0 1 3 3 3
i 0 0 0 0 0 0 3 3
t 0 0 0 0 0 0 0 3
首先,若原字符串和子序列都為空時(shí),返回1,因?yàn)榭沾彩强沾囊粋€(gè)子序列。若原字符串不為空,而子序列為空,也返回1,因?yàn)榭沾彩侨我庾址囊粋€(gè)子序列。而當(dāng)原字符串為空,子序列不為空時(shí),返回0,因?yàn)榉强兆址荒墚?dāng)空字符串的子序列。理清這些,二維數(shù)組 dp 的邊緣便可以初始化了,下面只要找出狀態(tài)轉(zhuǎn)移方程,就可以更新整個(gè) dp 數(shù)組了。我們通過觀察上面的二維數(shù)組可以發(fā)現(xiàn),當(dāng)更新到 dp[i][j] 時(shí),dp[i][j] >= dp[i][j - 1] 總是成立,再進(jìn)一步觀察發(fā)現(xiàn),當(dāng) T[i - 1] == S[j - 1] 時(shí),dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1],若不等, dp[i][j] = dp[i][j - 1],所以,綜合以上,遞推式為:
dp[i][j] = dp[i][j - 1] + (T[i - 1] == S[j - 1] ? dp[i - 1][j - 1] : 0)
根據(jù)以上分析,可以寫出代碼如下:
class Solution {
public:
int numDistinct(string s, string t) {
int m = s.size(), n = t.size();
vector<vector<long>> dp(n + 1, vector<long>(m + 1));
for (int j = 0; j <= m; ++j) dp[0][j] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
dp[i][j] = dp[i][j - 1] + (t[i - 1] == s[j - 1] ? dp[i - 1][j - 1] : 0);
}
}
return dp[n][m];
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/115
參考資料:
https://leetcode.com/problems/distinct-subsequences/
https://leetcode.com/problems/distinct-subsequences/discuss/37327/Easy-to-understand-DP-in-Java
到此這篇關(guān)于C++實(shí)現(xiàn)LeetCode(115.不同的子序列)的文章就介紹到這了,更多相關(guān)C++實(shí)現(xiàn)不同的子序列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++實(shí)現(xiàn)LeetCode(122.買股票的最佳時(shí)間之二)
- C++實(shí)現(xiàn)LeetCode(121.買賣股票的最佳時(shí)間)
- C++實(shí)現(xiàn)LeetCode(119.楊輝三角之二)
- C++實(shí)現(xiàn)LeetCode(118.楊輝三角)
- C++實(shí)現(xiàn)LeetCode(120.三角形)
- C++實(shí)現(xiàn)LeetCode(117.每個(gè)節(jié)點(diǎn)的右向指針之二)
- C++實(shí)現(xiàn)LeetCode(116.每個(gè)節(jié)點(diǎn)的右向指針)
- C++實(shí)現(xiàn)LeetCode(123.買股票的最佳時(shí)間之三)
相關(guān)文章
Qt GUI圖形圖像開發(fā)之QT表格控件QTableView詳細(xì)使用方法與實(shí)例
這篇文章主要介紹了Qt GUI圖形圖像開發(fā)之QT表格控件QTableView詳細(xì)使用方法與實(shí)例,需要的朋友可以參考下2020-03-03
關(guān)于c++ 智能指針及 循環(huán)引用的問題
下面小編就為大家?guī)硪黄P(guān)于c++ 智能指針及 循環(huán)引用的問題。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01
C++ DLL動(dòng)態(tài)庫的創(chuàng)建與調(diào)用(類庫,隱式調(diào)用)
本文主要介紹了C++ DLL動(dòng)態(tài)庫的創(chuàng)建與調(diào)用(類庫,隱式調(diào)用),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
C語言中棧的結(jié)構(gòu)和函數(shù)接口的使用示例
這篇文章主要介紹了C語言中棧的結(jié)構(gòu)和函數(shù)接口的使用,類似很多軟件都有撤銷的操作,這其實(shí)就是用棧這種方法來實(shí)現(xiàn)的,當(dāng)然不同的軟件具體實(shí)現(xiàn)代碼會(huì)有差異,不過原理大多都是一樣的2023-02-02
C++實(shí)現(xiàn)四則運(yùn)算器(無括號(hào))
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)四則運(yùn)算器,無括號(hào)的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11

