Java實(shí)現(xiàn)求數(shù)組最長(zhǎng)子序列算法示例
本文實(shí)例講述了Java實(shí)現(xiàn)求數(shù)組最長(zhǎng)子序列算法。分享給大家供大家參考,具體如下:
問題:給定一個(gè)長(zhǎng)度為N的數(shù)組,找出一個(gè)最長(zhǎng)的單調(diào)自增子序列(不一定連續(xù),但是順序不能亂) 例如:給定一個(gè)長(zhǎng)度為8的數(shù)組A{1,3,5,2,4,6,7,8},則其最長(zhǎng)的單調(diào)遞增子序列為{1,2,4,6,7,8},長(zhǎng)度為6。
思路1:第一眼看到題目,很多人肯定第一時(shí)間想到的是LCS。先給數(shù)組排個(gè)序形成新數(shù)組,然后再把新數(shù)組和原數(shù)組拿來求LCS,即可得到答案。這種解法很多人能想得到,所以就不再贅述。
思路2:按照思路1的想法,最后求LCS時(shí)還是得用到DP,我們干嘛不直接用DP來求解呢。對(duì)于數(shù)組arr,我們從后往前遍歷數(shù)組,分別求出當(dāng)子序列以arr[i]
結(jié)尾時(shí)的最長(zhǎng)子序列,然后取其中的最大值。即可得到整個(gè)數(shù)組的最長(zhǎng)子序列。 那么怎么求以arr[i]
結(jié)尾時(shí)的最長(zhǎng)子序列呢,這就轉(zhuǎn)換成一個(gè)DP問題了。要求arr[i]
的最長(zhǎng)子序列,只需要求出arr[i-1]
的最長(zhǎng)子序列。即:max{arr[i]}=max{arr[i-1]}+1
。
java實(shí)現(xiàn)代碼:
public class arrDemo { public static void main(String[] args) { // int[] arr = {89, 256, 78, 1, 46, 78, 8}; int[] arr = { 1, 3, 5, 2, 4, 6, 7, 8 }; // int[] arr = {6, 4, 8, 2, 17}; int max = 0; int maxLen = arr.length; // 從后往前遍歷數(shù)組,分別求出以arr[i]結(jié)尾的時(shí)候的最長(zhǎng)子序列長(zhǎng)度 for (int i = arr.length - 1; i > 0; i--) { int[] newArr = new int[i]; System.arraycopy(arr, 0, newArr, 0, i); int currentLength = 1 + dp(newArr, arr[i]); if (currentLength > max) max = currentLength; // 最長(zhǎng)子序列的長(zhǎng)度最長(zhǎng)為原始數(shù)組的長(zhǎng)度, // 因?yàn)椴恍枰覀兦笞铋L(zhǎng)子序列的元素,所以直接結(jié)束循環(huán),減少時(shí)間開銷 if (max == maxLen) break; } System.out.println(max); } public static int dp(int[] arr, int end) { // 遞歸結(jié)束條件 if (arr.length == 1) { // 小于end則包含在子序列中,子序列長(zhǎng)度+1 if (arr[0] <= end) return 1; else return 0; } // 遍歷數(shù)組,找到最靠近end的并且<=end的元素位置i for (int i = arr.length - 1; i >= 0; i--) { if (arr[i] <= end) { // 從i處截?cái)鄶?shù)組,將arr[0]到arr[i-1]組成新數(shù)組繼續(xù)遞歸求長(zhǎng)度 int[] newArr = new int[i]; System.arraycopy(arr, 0, newArr, 0, i); // 分別計(jì)算包含arr[i]時(shí)的最長(zhǎng)子序列和不包含arr[i]時(shí)的最長(zhǎng)子序列,取最大值 int containLen = dp(newArr, arr[i]) + 1; int notContainLen = dp(newArr, end); return containLen > notContainLen ? containLen : notContainLen; } } // 如果沒找到比end更小的,返回長(zhǎng)度為0 return 0; } }
運(yùn)行結(jié)果:
6
我的方法由于中間開辟了多個(gè)新數(shù)組,可能占用的空間有點(diǎn)多,不過我覺得應(yīng)該也不是很多- -,具體我也沒統(tǒng)計(jì)過。如果有不對(duì)的地方還請(qǐng)指正。
更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
Java Spring分別實(shí)現(xiàn)定時(shí)任務(wù)方法
這篇文章主要為大家詳細(xì)介紹了Java與Spring設(shè)置動(dòng)態(tài)定時(shí)任務(wù)的方法,定時(shí)任務(wù)的應(yīng)用場(chǎng)景十分廣泛,如定時(shí)清理文件、定時(shí)生成報(bào)表、定時(shí)數(shù)據(jù)同步備份等2022-07-07springboot單獨(dú)使用feign簡(jiǎn)化接口調(diào)用方式
這篇文章主要介紹了springboot單獨(dú)使用feign簡(jiǎn)化接口調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)順序表示例
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)順序表示例,需要的朋友可以參考下2014-03-03SpringBoot+layui實(shí)現(xiàn)文件上傳功能
Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開發(fā)過程。這篇文章主要介紹了SpringBoot+layui實(shí)現(xiàn)文件上傳,需要的朋友可以參考下2018-09-09Java實(shí)現(xiàn)音頻轉(zhuǎn)碼(WAV、MP3、AMR互轉(zhuǎn))
本文主要介紹了Java實(shí)現(xiàn)音頻轉(zhuǎn)碼,包括WAV、MP3、AMR互轉(zhuǎn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-02-02SpringBoot項(xiàng)目開發(fā)中常用的依賴
這篇文章主要介紹了SpringBoot項(xiàng)目開發(fā)中常用的依賴詳解,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06