Leetcode_6:子序列問題

子序列問題

最長連續遞增序列

給定一個未經排序的整數數組,找到最長且連續的的遞增序列。

思路: 要找一個最長且連續,關鍵是連續,那麼只要遍歷,發現不連續就歸零,記錄最大值即可。

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,當第ii個數大於Array中最大數,那麼就把nums[i]nums[i]添加到Array中;否則,則在Array中二分查找,查找大於nums[i]nums[i]數的最小下標index,然後nums[i]nums[i]替換Array[index]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,當遍歷到數組第ii個元素時nums[i]nums[i],將兩個變量分別與元素nums[i]nums[i]相乘,新的乘積值和nums[i]nums[i]相比較,值比較大的爲新的max_product=max(maxproductnums[i],nums[i])max\_product=max(max_product*nums[i], nums[i]),值比較小的爲新的min_product=min(minproductnums[i],nums[i])min\_product=min(min_product*nums[i], nums[i]),最後比較一下取max(productmaxproduct)max(product, max_product)作爲新的product。如果num[i]num[i]爲負數時,由於負數的性質,需要將最大乘積值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)是一個很經典的動態規劃問題。我們定義二維數組用來存儲最長公共子序列的長度,dp[i][j]dp[i][j]表示兩個字符串text1前ii個字符和字符串text2前jj個字符的最長公共子序列長度。

  • 那麼當text1[i]=text2[j]text1[i]=text2[j]時,最長公共序列加一,那麼dp[i][j]=dp[i1][j1]+1dp[i][j] = dp[i-1][j-1] + 1

  • text1[i]text2[j]text1[i] \neq text2[j]dp[i][j]dp[i][j]的最長公共子串存在於dp[i1][j]dp[i-1][j]或者dp[i][j1]dp[i][j-1]中,即dp[i][j]=max(dp[i][j1],dp[i][j1])dp[i][j] = max(dp[i][j-1], dp[i][j-1])

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];
    }
};

最長連續序列

給定一個未排序的整數數組,找出最長連續序列的長度。要求算法的時間複雜度爲O(n)O\left(n\right)

思路: 可以先對數組排序然後再遍歷找最長連續序列,可是最快的排序也需要O(nlogn)O\left(nlogn\right)。明確要求時間複雜度爲O(n)O\left(n\right)。怎麼辦呢?可以藉助數據結構,我們知道哈希的查找速度爲O(1)O\left(1\right)。原先想使用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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章