第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

1. 前言

在上個章節(jié)中我們討論了最常見的一維數(shù)組以及對應(yīng)一維狀態(tài)轉(zhuǎn)移方程的解決方案,但是動態(tài)規(guī)劃的難點在于很多情況下使用一維的狀態(tài)轉(zhuǎn)移方程并不能解決問題,需要使用二維甚至三維的轉(zhuǎn)移方程。多維方程的狀態(tài)轉(zhuǎn)移函數(shù)需要抽象不同對象,例如多個字符串或者數(shù)組之間的關(guān)系。

2. 最長公共子序列

面試官提問:給定兩個字符串,求解最長公共子序列。

題目解析

求解最長公共子序列問題是來源于算法網(wǎng)站LeetCode的經(jīng)典題目,題目鏈接:https://leetcode.com/problems/longest-common-subsequence/。

首先是明確子序列的定義,例如對于字符串imooc,那么im、imoimc都是它的子序列,子序列可以連續(xù)也可以不連續(xù),如果是連續(xù)出現(xiàn)的,例如字符串imoo,一般被叫做子序列串。

其次是明確公共子序列的定義,對于兩個字符串,如果包含相同的子序列,那么這個子序列就是兩個字符串的公共子序列,例如imoocmoocer的公共子序列就有mmo等,所有公共子序列中最長的子序列就是最長公共子序列(Longest Common Subsequence)。

首先從定性的角度來看,如果兩個字符串中,一個字符串的長度為零,那么最長公共子序列長度一定為零。

其次從定量的角度分析這個問題,例如給定的兩個字符串分別是X={x1,x2,x3 ... xm}Y={y1,y2,y3 ... ym},表示X字符串是通過x1、x2一直到xm個連續(xù)字符組成,Y字符串同理。求解動態(tài)規(guī)劃的通用方案是找到子問題的共性,字符串的子問題就是子字符串,我們假設(shè)X'={x1,x2,x3 ... xi}Y'={y1,y2,y3 ... yi} 的最長公共子序列是L,其中i<m。那么按照遞歸就有兩種狀態(tài)轉(zhuǎn)移流程:

(1)如果xi=yi,也就是兩個字符串的子字符串的最后一個字符剛好相等,那么{L,x(i+1)}或者{L,y{i+1}}就是新的最長公共子序列;

(2)如果xi≠yi,也就是兩個字符串的子字符串的最后一個字符并不相等,那么問題就可以轉(zhuǎn)換為求下面兩種情況的最長公共子序列:

第一種情況:X'={x1,x2,x3 ... x(i-1)} ,Y'={y1,y2,y3 ... yi}的最長公共子序列,假設(shè)為L1;
第二種情況:X'={x1,x2,x3 ... xi}Y'={y1,y2,y3 ... y(i-1)}的最長公共子序列,假設(shè)為L2。

最終需要的結(jié)果就是L = max(L1,L2)。

我們用 Java 語言實現(xiàn)上面描述的算法,示例:

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int n = text1.length();
        int m = text2.length();
        int[][] dp = new int[n+1][m+1];
        
        //設(shè)置dp方程初始值
        for(int i = 0; i < n+1; i++){
            for(int j = 0; j < m+1; j++){
                if(i == 0 || j == 0){
                    dp[i][j] = 0;
                }
            }
        }
        //循環(huán)更新狀態(tài)
        for(int i = 1; i < n+1; i++){
            for(int j = 1; j < m+1; j++){
                if(text1.charAt(i-1) == text2.charAt(j-1)){
                	//如果這個位置的字符相同,說明相對于dp[i-1][j-1]剛好長一個字符
                    dp[i][j] = 1 + dp[i-1][j-1];
                } else{
                	// 否則采用公共長度最長的
                    dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
                }
            }
        }
        
        //返回結(jié)果
        return dp[n][m];
    }
}

3. 小結(jié)

本章節(jié)介紹了動態(tài)規(guī)劃中最經(jīng)典的最長公共子序列問題,相對于一維數(shù)組下的動態(tài)規(guī)劃,二維數(shù)組的動態(tài)規(guī)劃一般不能壓縮空間,即時間復(fù)雜度基本都是O(n^2)的級別。字符串和動態(tài)規(guī)劃結(jié)合的類似問題還有最長上升子序列、字符串的編輯距離等。候選人需要從小型數(shù)據(jù)案例開始分析狀態(tài)轉(zhuǎn)移的核心,問題一般都能迎刃而解。