題目一(貪心)
?674. 最長連續(xù)遞增序列
難度:簡單
給定一個未經(jīng)排序的整數(shù)數(shù)組,找到最長且 連續(xù)遞增的子序列,并返回該序列的長度。
連續(xù)遞增的子序列 可以由兩個下標(biāo) l
和 r(l < r)
確定,如果對于每個 l <= i < r
,都有 nums[i] < nums[i + 1]
,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]]
就是連續(xù)遞增子序列。
示例 1:
輸入:nums = [1,3,5,4,7]
輸出:3
解釋:最長連續(xù)遞增序列是 [1,3,5], 長度為3。
盡管 [1,3,5,7] 也是升序的子序列, 但它不是連續(xù)的,因為 5 和 7 在原數(shù)組里被 4 隔開。
示例 2:
輸入:nums = [2,2,2,2,2]
輸出:1
解釋:最長連續(xù)遞增序列是 [2], 長度為1。
提示:
- 1 < = n u m s . l e n g t h < = 1 0 4 1 <= nums.length <= 10^4 1<=nums.length<=104
- ? 1 0 9 < = n u m s [ i ] < = 1 0 9 -10^9 <= nums[i] <= 10^9 ?109<=nums[i]<=109
??思路:貪心
這道題目可以用貪心來做:
- 遇到
nums[i] > nums[i - 1]
的情況,count
就++
, - 否則
count
為1
,使用ans
保存count
的最大值。
??代碼:(Java、C++)
Java
class Solution {
public int findLengthOfLCIS(int[] nums) {
int ans = 1, count = 1;;
for(int i = 1; i < nums.length; i++){
if(nums[i] > nums[i - 1]) count++;
else{
ans = Math.max(ans, count);
count = 1;
}
}
ans = Math.max(ans, count);
return ans;
}
}
C++
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
int ans = 1, count = 1;;
for(int i = 1; i < nums.size(); i++){
if(nums[i] > nums[i - 1]) count++;
else{
ans = max(ans, count);
count = 1;
}
}
ans = max(ans, count);
return ans;
}
};
?? 運(yùn)行結(jié)果:
?? 復(fù)雜度分析:
-
時間復(fù)雜度:
O
(
n
)
O(n)
O(n),其中
n
為數(shù)組nums
的長度,要遍歷數(shù)組一次。 - 空間復(fù)雜度: O ( 1 ) O(1) O(1),額外使用的空間為常數(shù)。
題目來源:力扣。文章來源:http://www.zghlxwxcb.cn/news/detail-453828.html
題目二(背包問題)
?718. 最長重復(fù)子數(shù)組
難度:中等
給兩個整數(shù)數(shù)組 nums1
和 nums2
,返回 兩個數(shù)組中 公共的 、長度最長的子數(shù)組的長度 。
示例 1:
輸入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
輸出:3
解釋:長度最長的公共子數(shù)組是 [3,2,1] 。
示例 2:
輸入:nums1 = [0,0,0,0,0], nums2 = [0,0,0,0,0]
輸出:5
提示:
- 1 <= nums1.length, nums2.length <= 1000
- 0 <= nums1[i], nums2[i] <= 100
??思路:動態(tài)規(guī)劃
背包問題必知內(nèi)容:一篇文章吃透背包問題?。?!
類似 0-1背包,我們可以設(shè)置一個二維dp
數(shù)組,dp[i][j]
表示nums1
的前i
個數(shù)字 和 nums2
的前j
個數(shù)字 的最長重復(fù)子數(shù)組長度:
- 如果
nums1[i] == nums2[j]
則此時的最長長度等于左上角的長度加1
,即狀態(tài)轉(zhuǎn)移公式為:
d p [ i ] [ j ] = d p [ i ? 1 ] [ j ? 1 ] + 1 dp[i][j] = dp[i-1][j-1] + 1 dp[i][j]=dp[i?1][j?1]+1 - 如果不相等,
dp[i][j] = 0
;
?? 空間優(yōu)化:
- 由上面的 狀態(tài)轉(zhuǎn)移公式 發(fā)現(xiàn),
dp[i][j]
只與dp[i-1][j-1]
有關(guān),所以可以只使用一維dp
數(shù)組即可,即狀態(tài)轉(zhuǎn)移公式 可變?yōu)椋?br> d p [ j ] = 1 + d p [ j ? 1 ] dp[j] = 1 + dp[j - 1] dp[j]=1+dp[j?1] - 又因為
dp[j]
使用的是變化前的dp[j-1]
,所以在程序?qū)崿F(xiàn)時需要按 倒序 來循環(huán)求解。
??代碼:(Java、C++)
Java
class Solution {
public int findLength(int[] nums1, int[] nums2) {
int[] dp = new int[nums2.length + 1];//dp[i]數(shù)組存儲
int ans = 0;
for(int i = 0; i < nums1.length; i++){
for(int j = nums2.length - 1; j >= 0; j--){
if(nums1[i] == nums2[j]){
dp[j + 1] = 1 + dp[j];
ans = Math.max(ans, dp[j + 1]);
}
else dp[j + 1] = 0;
}
}
return ans;
}
}
C++
class Solution {
public:
int findLength(vector<int>& nums1, vector<int>& nums2) {
vector<int> dp(nums2.size() + 1);//dp[i]數(shù)組存儲
int ans = 0;
for(int i = 0; i < nums1.size(); i++){
for(int j = nums2.size() - 1; j >= 0; j--){
if(nums1[i] == nums2[j]){
dp[j + 1] = 1 + dp[j];
ans = max(ans, dp[j + 1]);
}
else dp[j + 1] = 0;
}
}
return ans;
}
};
?? 運(yùn)行結(jié)果:
?? 復(fù)雜度分析:
-
時間復(fù)雜度:
O
(
n
?
m
)
O(n*m)
O(n?m),其中
n
為數(shù)組nums1
的長度,m
為數(shù)組nums2
的長度。 - 空間復(fù)雜度: O ( m ) O(m) O(m)。
題目來源:力扣。
放棄一件事很容易,每天能堅持一件事一定很酷,一起每日一題吧!
關(guān)注我LeetCode主頁 / CSDN —— 力扣專欄,每日更新!文章來源地址http://www.zghlxwxcb.cn/news/detail-453828.html
注: 如有不足,歡迎指正!
到了這里,關(guān)于( 動態(tài)規(guī)劃) 674. 最長連續(xù)遞增序列 / 718. 最長重復(fù)子數(shù)組——【Leetcode每日一題】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!