最長上升子序列(LIS)簡介及其例題分析

一.最長上升子序列(LIS)的相關知識

1.最長上升子序列(Longest? Increasing Subsequence),簡稱LIS,也有些情況求的是最長非降序子序列,二者區別就是序列中是否可以有相等的數。假設我們有一個序列 b i,當b1 < b2 < … < bS的時候,我們稱這個序列是上升的。

(或許我們剛開始對于這樣的名詞感到陌生,對于解釋也不理解,那我們就要知道它的前置知識)

?一.什么是子序列?

? ? 一個序列A={a1,a2,...an}中任意刪除若干項,剩余的序列叫做A的一個子序列。例如序列A={1,3,5,4,2},刪除其中的第3項和第5項,得到序列B={1,3,4},刪除其中的第3項和第4項,得到序列C={1,3,2},此時序列B和C是序列A的子序列。

二.什么是最長子序列?

? ? 如果序列中的元素是從小到大排列的,則該序列為上升序列,如果該序列又是其它序列的子序列,則稱為上升子序列。例如“1.1 子序列”中提到的B是A的上升子序列,而C是A的子序列,但不是上升子序列。

了解這兩個前置知識,那么最長上升子序列就很容易理解了。

即包含元素最多的上升子序列,叫做最長上升子序列。

?

?二.LIS長度的求解方法

一.方法一:動態規劃(O(n^2)樸素法)

動態規劃的一個特點就是當前解可以由上一個階段的解推出, 由此,把我們要求的問題簡化成一個更小的子問題。我們求最長上升子序列也符合這一特點,我們要求前n個數的最長上升子序列就是可以轉換成求前n-1個數的最長上升子序列......這樣逐步分解,直到求前1個數的最長上升子序列。

狀態轉移方程為:dp[i]=max(dp[i],dp[j]+1)

其核心代碼段為:

for (int i = 1; i <= n; i++) {for (int j = 1; j < i; j++) {if (a[i] > a[j])dp[i] = max(dp[i], dp[j] + 1);}}for (int i = 1; i <= n; i++) {ans = max(ans, dp[i]);}


?

二.方法二:貪心+二分(O(nlogn))

用一個low數組記錄長度,low[i]表示長度都為i的LIS結尾元素的最小值,這樣我們在記錄low的時候,當a[i]大于low[++當前LIS最大長度]時候,直接將a[i]接在low中,否則在low中二分查找大于等于當前元素a[i]的第一個位置pos,用a[i]替換掉之前的low[pos].最后我們找一下最長上升子序列下標滿足的解,記錄下該子序列即可.(注意,low數組不一定是最長上升子序列,只是長度對等)

這里的二分操作可以用STL中的lower_bound()函數實現。

核心代碼段:

low[++sum]=a[1];
for (int i = 2; i <= n; i++) {if (a[i] > low[sum])low[++sum] = a[i];else{int k = lower_bound(low + 1, low + sum + 1, a[i]) - dp;low[k] = a[i];}
}

?

三.例題分析

?一.B3637 最長上升子序列

?

?這一題就相當于最長上升子序列的模版題,通過動態規劃(樸素法)就可以解決,這里可以當做模版學習。

#include<bits/stdc++.h>
using namespace std;
#define N 1000005
int dp[N], a[N];
int ans, n, m, sum;
int main()
{cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];dp[i] = 1;           //初始化,dp都為1,即自身是一個上升子序列}for (int i = 1; i <= n; i++) {for (int j = 1; j < i; j++) {  //如果在之前的序列有小于a[i]的,更新dpif (a[i] > a[j])dp[i] = max(dp[i], dp[j] + 1);}}for (int i = 1; i <= n; i++) {ans = max(ans, dp[i]);   //找出最長的上升子序列}cout << ans << endl;return 0;
}

二.LIS

這一題和剛剛的題目的意思是一模一樣的,唯一的區別就是數據范圍變大了,變為1e5,如果我們還是和剛剛一樣使用O(n^2)的方法,肯定會超時,那么我們就應該使用方法二:貪心+二分? ? ? ?(O(nlogn))

#include<bits/stdc++.h>
using namespace std;
#define N 100005
int a[N], b[N];
int n, m, sum, ans;
int main()
{cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];}b[++sum] = a[1];     //核心代碼段,沒什么好說的for (int i = 2; i <= n; i++) {if (a[i] > b[sum])b[++sum] = a[i];else{int k = lower_bound(b + 1, b + sum + 1, a[i]) - b;b[k] = a[i];}}cout << sum << endl;return 0;
}

這里給大家留下兩道練習題,這兩道題都是在此基礎上的變形題,可以會有點難(都是洛谷上的題,可以看題解),后面我也會給出分析。

[ARC149B] Two LIS Sum

P8736 [藍橋杯 2020 國 B] 游園安排

另外,關于LIS還有一個姊妹叫作LCS(最長公共上上子序列),下次我們將講解相關內容,好了今天的內容就到這里了。~QVQ~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717833.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717833.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717833.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【論文筆記】Initializing Models with Larger Ones

Abstract 介紹權重選擇&#xff0c;一種通過從預訓練模型的較大模型中選擇權重子集來初始化較小模型的方法。這使得知識從預訓練的權重轉移到更小的模型。 它還可以與知識蒸餾一起使用。 權重選擇提供了一種在資源受限的環境中利用預訓練模型力量的新方法&#xff0c;希望能夠…

代碼隨想錄Day67 | 695.島嶼的最大面積 1020.飛地的數量

代碼隨想錄Day67 | 695.島嶼的最大面積 1020.飛地的數量 695.島嶼的最大面積1020.飛地的數量 695.島嶼的最大面積 文檔講解&#xff1a;代碼隨想錄 視頻講解&#xff1a; 狀態 采用bfs&#xff0c;這道題相較于之前的題變為了求島嶼的最大面積。那就說明我們每遇到一個新的島嶼…

【Linux】軟件管理yum | 編輯器vim | vim插件安裝

目錄 1. Linux軟件管理yum 1.1 什么是軟件包 1.2 查看軟件包 1.3 如何安裝軟件 1.4 如何卸載軟件 2. Linux編輯器vim 2.1 vim的基本概念 2.2 vim的基本操作 2.3 vim正常模式命令集 2.4 vim末行模式命令集 2.5 簡單vim配置 2.6 插件安裝 1. Vim-Plug 3. coc.nvim …

如何自己系統的學python

學習Python是一項很好的投資&#xff0c;因為它是一種既強大又易于學習的編程語言&#xff0c;適用于多種應用&#xff0c;如數據分析、人工智能、網站開發等。下面是一個系統學習Python的步驟建議&#xff1a; 基礎準備 安裝Python&#xff1a; 訪問Python官網下載最新版本的…

微服務獲取當前登錄用戶信息

一&#xff0c;實現思路 1&#xff0c;基于JWT令牌登陸方式 JWT實現登錄的&#xff0c;登錄信息就保存在請求頭的token中。因此要獲取當前登錄用戶&#xff0c;只要獲取請求頭&#xff0c;解析其中的token。 1&#xff09;&#xff0c;Gateway網關攔截&#xff0c;解析用戶信…

微信小程序-生命周期

頁面生命周期 onLoad: 頁面加載時觸發的方法&#xff0c;在這個方法中可以進行頁面初始化的操作&#xff0c;如獲取數據、設置頁面狀態等。 onShow: 頁面顯示時觸發的方法&#xff0c;在用戶進入頁面或從其他頁面返回該頁面時會調用此方法。可以在此方法中進行頁面數據刷新、動…

Onenote軟件新建筆記本時報錯:無法在以下位置新建筆記本

報錯現象&#xff1a; 當在OneNote軟件上&#xff0c;新建筆記本時&#xff1a; 然后&#xff0c;嘗試重新登錄微軟賬戶&#xff0c;也不行&#xff0c;提示報錯&#xff1a; 解決辦法&#xff1a; 打開一個新的記事本&#xff0c;復制粘貼以下內容&#xff1a; C:\Users\Adm…

Mysql中的事務

什么是事務&#xff1a; 多條sql語句&#xff0c;要么全部成功&#xff0c;要么全部失敗。 事務的特性&#xff1a; 1&#xff1a;原子性(Atomic)&#xff1a; 組成一個事務的多個數據庫操作是一個不可分割的原子單元&#xff0c;只有所有操作都成功&#xff0c;整個事務才會…

在Unity中模擬實現手勢識別功能

在虛擬現實(VR)和增強現實(AR)的應用開發中&#xff0c;手勢識別技術扮演著至關重要的角色&#xff0c;它允許用戶以自然的方式與虛擬世界進行交云。然而&#xff0c;并非所有開發者都有條件使用真實的手勢識別硬件。本文介紹了如何在Unity中通過模擬的方式實現一個簡單的手勢識…

【LeetCode】1768_交替合并字符串_C

題目描述 給你兩個字符串 word1 和 word2 。請你從 word1 開始&#xff0c;通過交替添加字母來合并字符串。如果一個字符串比另一個字符串長&#xff0c;就將多出來的字母追加到合并后字符串的末尾。 返回 合并后的字符串 。 https://leetcode.cn/problems/merge-strings-al…

C++調用lua函數

C 調用Lua全局變量(普通) lua_getglobal(lua, "width");int width lua_tointeger(lua,-1);lua_pop(lua,1);std::cout << width << std::endl;lua_close(lua); 這幾行代碼要放到lua_pcall(lua, 0,0,0);之后才可以. C給lua傳遞變量 lua_pushstring(lua, …

Python 操作 Excel,如何又快又好?

?數據處理是 Python 的一大應用場景&#xff0c;而 Excel 則是最流行的數據處理軟件。因此用 Python 進行數據相關的工作時&#xff0c;難免要和 Excel 打交道。Python處理Excel 常用的系列庫有&#xff1a;xlrd、xlwt、xlutils、openpyxl ?xlrd &#xff0d; 用于讀取 Exce…

點云從入門到精通技術詳解100篇-基于點云網絡和 PSO 優化算法的手勢估計(續)

目錄 3 深度圖像處理及轉化 3.1 雙目深度攝像原理及深度圖的獲取 3.1.1 理想化雙目深度相機成像

day47_servlet

今日內容 0 復習昨日 1 接收請求 2 處理響應 0 復習昨日 HTTP請求中 請求行 請求方法,請求路徑 請求頭 頁面信息 請求正文 請求的數據 HTTP響應中 響應行 狀態碼 信息 響應頭 頁面信息 響應正文 要給瀏覽器的內容 1 接收請求 瀏覽器發出請求,經過web.xml映射匹配,找到Servlet…

STL容器之map和set

map和set ? c98支持的是單參數的隱式類型轉換&#xff0c;而c11支持多參數的隱式類型轉換&#xff1b; 1.map和set的使用 1.1set ? set實現key值不允許修改&#xff0c;是將iterator轉變成const_iterator&#xff1b;可以對同一個類型typedef成兩個不同的自定義標識符。即…

Rocky 9 安裝 R-CytoTRACE

官網給出的詳細指南&#xff0c;只是可能大家打不開或者懶得去看E文。 第一步&#xff0c;下載CytoTRACE安裝包。 wget https://cytotrace.stanford.edu/CytoTRACE_0.3.3.tar.gz 第二步&#xff0c;打開R或者Rstudio-server # 安裝依賴包 if (!requireNamespace("Bioc…

在vue中$nextTick 原理及作用

在vue中$nextTick 原理及作用 Vue 的 nextTick 其本質是對 JavaScript 執行原理 EventLoop 的一種應用。 nextTick 的核心是利用了如 Promise 、MutationObserver、setImmediate、setTimeout的原生 JavaScript 方法來模擬對應的微/宏任務的實現&#xff0c;本質是為了利用 Java…

每周AI新聞(2024年第9周)微軟與Mistral AI達成合作 | 谷歌發11B基礎世界模型 | 傳蘋果放棄電動汽車制造轉向生成式AI

這里是陌小北&#xff0c;一個正在研究硅基生命的碳基生命。正在努力成為寫代碼的里面背詩最多的&#xff0c;背詩的里面最會寫段子的&#xff0c;寫段子的里面代碼寫得最好的…廚子。 每周日解讀每周AI大事件。 大廠動向 【1】微軟與Mistral AI達成合作 微軟官宣與法國生成…

視頻云平臺——搭建SRS5平臺支持GB28181視頻流的推送

&#x1f4e2;歡迎點贊 &#xff1a;&#x1f44d; 收藏 ?留言 &#x1f4dd; 如有錯誤敬請指正&#xff0c;賜人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原創&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;我們面對的不僅…

謹用ArrayList中的subList方法

謹用ArrayList中的subList方法 規范一&#xff1a; ArrayList 的 subList 結果不可強轉成 ArrayList&#xff0c;否則會拋出 ClassCastException 異常&#xff1a; public static void test7() {List<Integer> list new ArrayList<>();list.add(1);list.add(2);…