子序列問題
最長連續遞增序列
給定一個未經排序的整數數組,找到最長且連續的的遞增序列。
思路: 要找一個最長且連續,關鍵是連續,那麼只要遍歷,發現不連續就歸零,記錄最大值即可。
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
int n = nums.size();
if(!n) return 0;
int max_num = 1;
int index = 1;
int tmp = nums[0];
for(int i=1;i<n;i++){
if(nums[i] >tmp){
index ++;
}else{
index = 1;
}
tmp = nums[i];
max_num = max_num < index ? index : max_num;
}
return max_num;
}
};
最長上升子序列
給定一個無序的整數數組nums,找到其中最長上升子序列的長度。
思路: 那要做怎麼新開一個數組Array記錄上升子序列,遍歷nums,當第個數大於Array中最大數,那麼就把添加到Array中;否則,則在Array中二分查找,查找大於數的最小下標index,然後替換。最後Array數組裏面元素的數目就是最長上升子序列的長度。
class Solution {
public:
int binary_search(vector<int>& A, int num){
int low = 0;
int high = A.size();
int mid = high / 2;
while(low<high){
mid = (low + high) / 2;
if(A[mid]<num){
low = mid + 1;
}else{
high = mid;
}
}
return low;
}
int lengthOfLIS(vector<int>& nums) {
vector<int> Array;
if(nums.size() == 0) return 0;
Array.push_back(nums[0]);
int max_num = Array[0];
for(int i=1;i<nums.size();i++){
if(nums[i] > max_num){
Array.push_back(nums[i]);
max_num = nums[i];
}else{
int index = binary_search(Array, nums[i]);
Array[index] = nums[i];
int len = Array.size();
max_num = Array[len - 1];
}
}
return Array.size();
}
};
乘積最大子序列
給定一個整數數組 nums ,找出一個序列中乘積最大的連續子序列(該序列至少包含一個數)。
思路: 首先聲明一個變量表示當前連續子序列的最大乘積product,然後再聲明兩個變量分別記錄當前的最大乘積值max_product和最小乘積值min_product,當遍歷到數組第個元素時,將兩個變量分別與元素相乘,新的乘積值和相比較,值比較大的爲新的,值比較小的爲新的,最後比較一下取作爲新的product。如果爲負數時,由於負數的性質,需要將最大乘積值max_product和最小乘積值min_product進行對換。
class Solution {
public:
int Max(int a, int b){
return a>b?a:b;
}
int Min(int a, int b){
return a<b?a:b;
}
int maxProduct(vector<int>& nums) {
int len = nums.size();
if(len==0) return 0;
int max_product = 1;
int min_product = 1;
int final_product = INT_MIN;
for(int i=0;i<len;i++){
if(nums[i]<0){
int tmp = max_product;
max_product = min_product;
min_product = tmp;
}
max_product = Max(max_product*nums[i], nums[i]);
min_product = Min(min_product*nums[i], nums[i]);
final_product = Max(max_product, final_product);
}
return final_product;
}
};
最長公共子序列
給定兩個字符串 text1 和 text2,返回這兩個字符串的最長公共子序列。
一個字符串的 子序列 是指這樣一個新的字符串:它是由原字符串在不改變字符的相對順序的情況下刪除某些字符(也可以不刪除任何字符)後組成的新字符串。
思路: 最長公共子序列問題(LCS)是一個很經典的動態規劃問題。我們定義二維數組用來存儲最長公共子序列的長度,表示兩個字符串text1前個字符和字符串text2前個字符的最長公共子序列長度。
-
那麼當時,最長公共序列加一,那麼。
-
當,的最長公共子串存在於或者中,即。
class Solution {
public:
int Max(int a,int b){
return a>b?a:b;
}
int longestCommonSubsequence(string text1, string text2) {
int len_1 = text1.length();
int len_2 = text2.length();
vector<vector<int>> res(len_1+1, vector<int>(len_2+1, 0));
for(int i=0;i<len_1;i++){
for(int j=0;j<len_2;j++){
if(text1[i] == text2[j]){
res[i+1][j+1] = res[i][j] + 1;
}else{
res[i+1][j+1] = Max(res[i][j+1], res[i+1][j]);
}
}
}
return res[len_1][len_2];
}
};
最長連續序列
給定一個未排序的整數數組,找出最長連續序列的長度。要求算法的時間複雜度爲。
思路: 可以先對數組排序然後再遍歷找最長連續序列,可是最快的排序也需要。明確要求時間複雜度爲。怎麼辦呢?可以藉助數據結構,我們知道哈希的查找速度爲。原先想使用hash_set,但是報錯,用了unordered_set無bug,說是C++11中不包含hash_set。
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int n = nums.size();
if(!n) return 0;
unordered_set<int> Set;
for(int i=0;i<n;i++){
Set.insert(nums[i]);
}
vector<int> flag(n, 1);
int max_num = INT_MIN;
for(int i=0;i<n;i++){
int index = 0;
int x = nums[i];
while(Set.find(x)!=Set.end()){
x++;
index++;
}
max_num = max_num < index ? index : max_num;
}
return max_num;
}
};