刷題 動態規劃專題(三)序列型別

2021-10-07 17:43:36 字數 3506 閱讀 8762

劍指 offer 42. 連續子陣列的最大和
分析:

1.dp[i]:以nums[i]作為結尾的最大連續序列和

2.dp[i] = max(dp[i-1]+nums[i],nums[i])

看當前元素加在上乙個最大序列之後得到的和大,還是將當前元素作為乙個新的開始得到的和大。

3.比較所有元素作為結尾得到的連續子陣列和的大小。

4.初始化:因為至少選擇陣列中的乙個數,所以當只有乙個元素時,最大和就是元素的值,dp[0] = nums[0]。

class

solution

return ans;}}

;

300. 最長上公升子串行

給定乙個無序的整數陣列,找到其中最長上公升子串行的長度。

示例:輸入: [10,9,2,5,3,7,101,18]

輸出: 4

解釋: 最長的上公升子串行是 [2,3,7,101],它的長度是 4。

說明:可能會有多種最長上公升子串行的組合,你只需要輸出對應的長度即可。

你演算法的時間複雜度應該為 o(n2) 。

高階: 你能將演算法的時間複雜度降低到 o(n log n) 嗎?

子串行:可以不連續

連續子串行:連續的

分析:1.dp[i]:以nums[i]作為結尾的最長上公升子串行長度

2.假設現在已知dp[0]…dp[i-1] 分別以nums[0]…nums[i-1]作為結尾的最長上公升子串行長度,如果想要在加入nums[i]後依然是最長上公升子串行,就需要判斷兩個條件:nums[i]是否大於nums[j],nums[i]加在哪個序列後才能得到最長。

dp[i] = max(dp[0]+1,…,dp[j]+1,…,dp[i-1]+1,1)(nums[j]class

solution

res =

max(res,dp[i]);

}return res;}}

;

1143. 最長公共子串行
分析:

1.dp[i][j]:以text1[i],text2[j]分別為結尾的序列的最長公共子串行長度。

2.轉移方程

3.初始狀態:需要注意的是text1[0]和text2[j]的最長公共子串行長度只能是1,也就是說text1[0]和text2[j]相同時,dp[0][j] =1,不同時dp[0][j]=dp[0][j-1]。dp[i][0]同理。

class

solution

for(

int i=

1;i)for

(int i=

1;ireturn res;}}

;

516. 最長回文子串行
1.dp[i][j]:以s[i]作為開頭,s[j]作為結尾的序列中包含的最長回文子串行長度

*note:這裡的dp[i][j]是指想要求的回文序列包含在是s[i…j]裡面的,而不是回文序列就是s[i…j]。而最大連續子串行和最長上公升子串行的dp[i]都是a[i]一定在目標序列中。要注意區別。

2.轉移方程

3.初始化:單個字母也是回文,所以對角線上的元素為1。而且作為開頭的字母在序列中給的下標應該小於結尾的下標,所以矩陣應該是乙個上三角矩陣,下三角的部分都初始化為0。

4.計算順序:從下到上,從左到右。

class

solution

for(

int i=n-

1;i>=

0;i--)}

return dp[0]

[n-1];}};

5. 最長回文子串

給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。

示例 1:

輸入: 「babad」

輸出: 「bab」

注意: 「aba」 也是乙個有效答案。

示例 2:

輸入: 「cbbd」

輸出: 「bb」

這個題和上個題的區別在於,乙個是求最長回文串長度乙個是求最長回文串,在思路上是一脈相承的。只要在每次比較最長回文長度時,記錄下起始位置和長度即可。

1.dp[i][j]:s[i.j]是否是乙個回文串。

3.單個字元和兩個字元時都可以直接判斷,所以初始化不僅要初始化對角線上的,還要初始化(i,i+1)位置上的。

4.計算順序同上題。

class

solution

if(dp[i]

[i]==1&&

1>len)

if(i!=n-

1&&dp[i]

[i+1]==

1&&2>len)

}for

(int i=n-

1;i>=

0;i--)}

}return s.

substr

(start,len);}

};

*note:substr()的用法是傳入起始位置和擷取長度。

139. 單詞拆分
1.dp[i]:到第i個字母構成的序列是否滿足條件

2.dp[i]=dp[j]&&(s[j+1…i]在單詞表中)

3.j代表的含義就是分割序列的位置,j及其之前的序列是否符合條件由上一輪計算得到,所以i是對字串s的遍歷,而j是列舉可能的分割點。

需要注意的是:

i)當已經找到乙個合適的分割使dp[i]等於1,就不用再往下迴圈了,不然就會覆蓋正確答案。

ii)j應該小於i,而不是等於i結束內層迴圈,j=i時需要判斷的字串就是空的,沒有必要。

4.初始化:dp[0] = true,dp[0]代表的並不是下標為0的字元是否滿足條件,而是乙個字元都沒有的情況。dp[i]中的i比字串下標多1,也就是說dp[i]對應的是s[0…i-1],需要判斷的是s[j…i-1]。

class

solution

vector<

bool

>

dp(s.

size()

+1);

//dp[i]:到第i個字母的序列是否滿足條件

dp[0]

=true

;for

(int i=

1;i<=s.

size()

;i++)}

return dp[s.

size()

];}}

;

刷題86 動態規劃(三)

題目鏈結題目描述 給定乙個非負整數 num。對於 0 i num 範圍中的每個數字 i 計算其二進位制數中的 1 的數目並將它們作為陣列返回。示例 1 輸入 2 輸出 0,1,1 示例 2 輸入 5 輸出 0,1,1,2,1,2 高階 題目分析 法一 動態規劃 找規律 奇數二進位制中1的個數比前乙個...

LeetCode刷題 動態規劃(三)

最長公共子串行問題,最基本的問題是在兩個字串中找出最長公共字串。方法是使用雙指標 i,j遍歷兩個字串,建立二維 dp 陣列,通過填表獲得結果。1143,最長公共子串行,medium 583,兩個字串的刪除操作,medium 712,兩個字串的最小ascii刪除和,medium 1143,最長公共子串...

leetcode演算法刷題 五 動態規劃 三

今天的題目不是leetcode上面的。只是覺得動態規劃還是不算很熟練,就接著找了點dp的題練練 題目的意思 傳入乙個陣列,要求出它的最長遞增子串行的長度。例如 如在序列1,1,2,3,4,5,6,7中,最長遞增序列為1,2,4,6,所以長度為4。分析 這道題我們可以用動態規劃來做。對於陣列的前i個元...