国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

動態(tài)規(guī)劃算法 | 最長遞增子序列

這篇具有很好參考價值的文章主要介紹了動態(tài)規(guī)劃算法 | 最長遞增子序列。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

通過查閱相關(guān)資料發(fā)現(xiàn)動態(tài)規(guī)劃問題一般就是求解最值問題。這種方法在解決一些問題時應(yīng)用比較多,比如求最長遞增子序列等。

有部分人認為動態(tài)規(guī)劃的核心就是:窮舉。因為要求最值,肯定要把所有可行的答案窮舉出來,然后在其中找最值。

首先,筆者認為動態(tài)規(guī)劃中的窮舉有一定的特點,因為這類問題有重疊的子問題存在,暴力窮舉效率極其低下,所以需要“備忘錄(DP Table)”優(yōu)化窮舉過程,從而盡可能的避免不必要的計算。其次,動態(tài)規(guī)劃問題一定有“最優(yōu)子結(jié)構(gòu)”,只有這樣才能通過子問題的最值得到原問題的最值。另外,窮舉所有可行解通常較為困難,只有列出正確的“狀態(tài)轉(zhuǎn)移方程”才能正確地窮舉。

上述的重疊子問題、最優(yōu)子結(jié)構(gòu)、狀態(tài)轉(zhuǎn)移方程就是動態(tài)規(guī)劃三要素。在實際應(yīng)用中寫出狀態(tài)轉(zhuǎn)移方程是最困難的。通常根據(jù) “明確問題狀態(tài)?-> 定義 dp 數(shù)組/函數(shù)的具體含義 -> 明確轉(zhuǎn)移 -> 明確基本實例” 來構(gòu)建狀態(tài)轉(zhuǎn)移方程。

最長遞增子序列 LeetCode#300

dp[i] 表示當(dāng)最后一個數(shù)值為 nums[i] 時,此時對應(yīng)的最長遞增子序列的長度是 dp[i]。在下述例子中當(dāng) i=2 時 dp[2] 表示當(dāng)最后一個數(shù)為 3 時,對于數(shù)組 {1, 4, 3} 中最長遞增子序列的長度 dp[2]=2。

動態(tài)規(guī)劃算法 | 最長遞增子序列

基于動態(tài)規(guī)劃理論,當(dāng)已知前面第 i - 1 個值時,可以利用下述代碼求解得到第 i?個值。

for (int j = 0; j < i; j++) {
    if (nums[j] < nums[i]) {
        dp[i] = max(dp[i], dp[j] + 1);
    }
}

當(dāng)?shù)玫?dp 數(shù)組后,只需要求得 dp 數(shù)組的最大值(即為最大遞增子序列的長度)即可。

int ret = 1;
for (auto it : dp) {
    ret = max(ret, it);
}

普通動態(tài)規(guī)劃算法?O(N^2)

因此可以利用該方法解決 #300 問題,具體代碼如下所示。但是該算法的時間復(fù)雜度為 O(n^2),這對于較大數(shù)據(jù)量而言,性能不太能接受。

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int length = nums.size();
        vector<int> dp(length, 1);
        for (int i = 0; i < length; i++) {
            //對于某一個還未計算的dp[i],在nums的前i個中找到比nums[i]小的dp[j],
            //然后進行加1;可能會出現(xiàn)多個滿足的dp[j],取其中值最大的一個作為最終結(jié)果。
            for (int j = 0; j < i; j++) {
                if (nums[j] < nums[i]) {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
        }
        //找到dp數(shù)組中的最大值(也就是最長遞增子序列的長度)
        int ret = 1;
        for (auto it : dp) {
            ret = max(ret, it);
        }
        return ret;
    }
};

優(yōu)化動態(tài)規(guī)劃算法 O(NlogN)

對于該方法的具體優(yōu)化可以參考?動態(tài)規(guī)劃設(shè)計之最長遞增子序列

該算法的思路有點像游戲 “空當(dāng)接龍”,也就是對于每一張撲克牌,數(shù)值小的牌只能放在大牌的堆上面,當(dāng)沒有合適的堆時,新建一個堆放置該撲克牌;當(dāng)有多個滿足條件的堆時,將撲克牌放在最左端的堆上面(保證撲克牌堆頂?shù)呐朴行颍?/p>

#define MAX_HEAP 2500
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int heap_top_num[MAX_HEAP];
        int heap_cnt = 0;
        for (auto num : nums) {
            int left = 0;
            //對于每一個 num,區(qū)間右邊的值需要重新設(shè)置初始值。
            int right = heap_cnt;
            while (left < right) {
                int mid = (left + right) >> 1;
                //找到最先大于 num 的堆定元素
                if (heap_top_num[mid] >= num) {
                    right = mid;
                }
                else {
                    left = mid + 1;
                }
            }
            //當(dāng)沒有找到符合條件的 mid 時,退出條件是最右端區(qū)間位置,也就是 heap_cnt。
            //此時需要新建一個數(shù)值堆
            if (left == heap_cnt) {
                heap_cnt++;
            }
            heap_top_num[left] = num;
        }
        //堆的個數(shù)就是最長遞增子序列的長度
        return heap_cnt;
    }
};

轉(zhuǎn)變最長遞增子序列應(yīng)用 LeetCode#354

這道題目需要按照第一維參數(shù)進行升序排序,然后按照第二維參數(shù)降序排序(該維度中找出最長遞增子序列即可)。

注意點對于二維的 vector<vector<int>> 按照用戶自定義排序方式進行排序。

首先按照第一維度進行升序排序,如果第一維度元素相等,則按照第二維度進行降序排序。這里平時寫的重載的邏輯有所不一致,需要特別注意。文章來源地址http://www.zghlxwxcb.cn/news/detail-456891.html

sort(envelopes.begin(), envelopes.end(), 
    [](const vector<int>& a, const vector<int>& b) {
            return a[0] == b[0] ? a[1] > b[1]: a[0] < b[0];
            });
#define MAX_EN 100002
class Solution {
public:
    int heap_top[MAX_EN];
    int max_evlp;
    //利用二分法求解最長遞增子序列的長度。
    int longIncSub(vector<vector<int>>& sorted_subs) {
        for (int i = 0; i < max_evlp; i++) {
            heap_top[i] = 1;
        }

        int sub_cnt = 0;
        for (const auto& evlp : sorted_subs) {
            int left = 0;
            int right = sub_cnt;
            while (left < right) {
                int mid = (left + right) >> 1;
                if (heap_top[mid] >= evlp[1]) {
                    right = mid;
                }
                else {
                    left = mid + 1;
                }
            }

            if (left == sub_cnt) {
                sub_cnt++;
            }
            heap_top[left] = evlp[1];
        }
        return sub_cnt;
    }

    int maxEnvelopes(vector<vector<int>>& envelopes) {
        max_evlp = envelopes.size();
        //對二維vector按照用戶需要的排序規(guī)則進行排序方法。
        sort(envelopes.begin(), envelopes.end(), [](const vector<int>& a, const vector<int>& b) {
            return a[0] == b[0] ? a[1] > b[1]: a[0] < b[0];
            });

        return longIncSub(envelopes);
    }
};

到了這里,關(guān)于動態(tài)規(guī)劃算法 | 最長遞增子序列的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • LeetCode | C++ 動態(tài)規(guī)劃——300.最長遞增子序列、674. 最長連續(xù)遞增序列、718. 最長重復(fù)子數(shù)組

    300題目鏈接 dp 數(shù)組定義 dp[i] 表示 i 之前包括 i 的以 nums[i]結(jié)尾 的最長遞增子序列的長度 需要包含nums[i]結(jié)尾,不然在做遞增比較的時候,就沒有意義了。 遞推公式 位置 i 的最長遞增子序列 等于 j 從 0 到 i - 1各個位置的最長遞增子序列 + 1 的 最大值 if (nums[i] nums[j]) dp[i] = ma

    2024年02月16日
    瀏覽(49)
  • 【動態(tài)規(guī)劃】求最長遞增子序列問題

    【動態(tài)規(guī)劃】求最長遞增子序列問題

    最長遞增子序列(Longest Increasing Subsequence, LIS ) 子序列:對于任意序列s,它的子序列是通過刪除其中零個或多個元素得到的另?個序列 注:剩余元素的相對順序保持不變 給定n個整數(shù)組成的序列 s [ 1... n ] s[1...n] s [ 1... n ] ,求最長遞增子序列LIS(的長度) 8 3 6 1 3 5 4 7 假設(shè)

    2024年02月03日
    瀏覽(27)
  • 力扣--動態(tài)規(guī)劃300.最長遞增子序列

    力扣--動態(tài)規(guī)劃300.最長遞增子序列

    一開始想到的方法非常低效,但好理解。 ? 思路分析: 使用二維數(shù)組 dp 來記錄遞增子序列的長度信息,其中 dp[i][0] 表示以 nums[i] 結(jié)尾的最長遞增子序列的長度, dp[i][1] 表示包含 nums[i] 的最長遞增子序列的長度。 初始化 dp 數(shù)組,將以第一個元素結(jié)尾的遞增子序列長度置為

    2024年01月24日
    瀏覽(26)
  • 動態(tài)規(guī)劃9:最長遞增子序列、最長連續(xù)遞增序列、最長重復(fù)子數(shù)組、最長公共子序列、不相交的線、最長子序和

    動態(tài)規(guī)劃9:最長遞增子序列、最長連續(xù)遞增序列、最長重復(fù)子數(shù)組、最長公共子序列、不相交的線、最長子序和

    例題300: 給你一個整數(shù)數(shù)組 nums ,找到其中最長嚴格遞增子序列的長度。 子序列 是由數(shù)組派生而來的序列,刪除(或不刪除)數(shù)組中的元素而不改變其余元素的順序。例如,[3,6,2,7] 是數(shù)組 [0,3,1,6,2,2,7] 的子序列。 確定dp數(shù)組和下標含義 dp[i]表示在第i個元素的最長子序列數(shù)

    2024年04月08日
    瀏覽(29)
  • 【學(xué)會動態(tài)規(guī)劃】最長遞增子序列的個數(shù)(28)

    【學(xué)會動態(tài)規(guī)劃】最長遞增子序列的個數(shù)(28)

    目錄 動態(tài)規(guī)劃怎么學(xué)? 1. 題目解析 2. 算法原理 1. 狀態(tài)表示 2. 狀態(tài)轉(zhuǎn)移方程 3. 初始化 4. 填表順序 5. 返回值 3. 代碼編寫 寫在最后: 學(xué)習(xí)一個算法沒有捷徑,更何況是學(xué)習(xí)動態(tài)規(guī)劃, 跟我一起刷動態(tài)規(guī)劃算法題,一起學(xué)會動態(tài)規(guī)劃! 這道題的題目非常好理解,就是求出最長

    2024年02月11日
    瀏覽(26)
  • 【LeetCode: 673. 最長遞增子序列的個數(shù) | 動態(tài)規(guī)劃】

    【LeetCode: 673. 最長遞增子序列的個數(shù) | 動態(tài)規(guī)劃】

    ?? 算法題 ?? ?? 算法刷題專欄 | 面試必備算法 | 面試高頻算法 ?? ?? 越難的東西,越要努力堅持,因為它具有很高的價值,算法就是這樣? ?? 作者簡介:碩風(fēng)和煒,CSDN-Java領(lǐng)域新星創(chuàng)作者??,保研|國家獎學(xué)金|高中學(xué)習(xí)JAVA|大學(xué)完善JAVA開發(fā)技術(shù)棧|面試刷題|面經(jīng)八股文

    2024年02月03日
    瀏覽(22)
  • leetcode300. 最長遞增子序列(動態(tài)規(guī)劃-java)

    leetcode300. 最長遞增子序列(動態(tài)規(guī)劃-java)

    來源:力扣(LeetCode) 鏈接:https://leetcode.cn/problems/longest-increasing-subsequence 給你一個整數(shù)數(shù)組 nums ,找到其中最長嚴格遞增子序列的長度。 子序列 是由數(shù)組派生而來的序列,刪除(或不刪除)數(shù)組中的元素而不改變其余元素的順序。例如,[3,6,2,7] 是數(shù)組 [0,3,1,6,2,2,7] 的子序

    2024年02月15日
    瀏覽(20)
  • 力扣300:最長遞增子序列(Java動態(tài)規(guī)劃+雙指針)

    給你一個整數(shù)數(shù)組 nums ,找到其中最長嚴格遞增子序列的長度。 子序列?是由數(shù)組派生而來的序列,刪除(或不刪除)數(shù)組中的元素而不改變其余元素的順序。例如,[3,6,2,7] 是數(shù)組 [0,3,1,6,2,2,7] 的子序列。 ? 示例 1: 輸入:nums = [10,9,2,5,3,7,101,18] 輸出:4 解釋:最長遞增子序

    2024年02月12日
    瀏覽(27)
  • ( 動態(tài)規(guī)劃) 674. 最長連續(xù)遞增序列 / 718. 最長重復(fù)子數(shù)組——【Leetcode每日一題】

    ( 動態(tài)規(guī)劃) 674. 最長連續(xù)遞增序列 / 718. 最長重復(fù)子數(shù)組——【Leetcode每日一題】

    難度:簡單 給定一個未經(jīng)排序的整數(shù)數(shù)組,找到最長且 連續(xù)遞增的子序列 ,并返回該序列的長度。 連續(xù)遞增的子序列 可以由兩個下標 l 和 r(l r) 確定,如果對于每個 l = i r ,都有 nums[i] nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是連續(xù)遞增子序列。

    2024年02月05日
    瀏覽(24)
  • 算法 矩陣最長遞增路徑-(遞歸回溯+動態(tài)規(guī)劃)

    ??途W(wǎng): BM61 求矩陣的最長遞增路徑 解題思路: 1. 遍歷二維矩陣每個位置,max求出所有位置分別為終點時的最長路徑 2. 求某個位置為終點的最長路徑時,使用動態(tài)規(guī)劃dp對已經(jīng)計算出的位置進行記錄 3. 處理某個位置的最長路徑時,如果dp[i][j]位置已有值,則直接返回即可,否則

    2024年02月07日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包