幾個常見的DP問題及解法

2021-07-15 23:00:37 字數 2071 閱讀 3567

記錄一些最近遇到的dp問題,並給出解法。只會記錄我知道的最優解法(一般是時間最優),並貼出原始碼。有oj的還會貼上位址。

舉例:

問題分析:

記字串存放在字元陣列cs中,遍歷cs的下標為i。分析可知,想求截止到i的最長不重複子串的長度,只要從i向左,找到第1個重複的字元,其右邊的數標記為left,則所求長度就是i-left+1與之前求得的結果中的最大值。舉例說明:

經分析可知,該演算法需要在每一次遍歷時,向左查詢0~i個不等的元素,所以時間複雜度是o(n2),空間複雜度o(1)。

上述方案尚有優化的空間,是因為在尋找left時採用了簡單的遍歷。經過分析可以知道left的變化是有規律的。只要知道與cs[i]相同的字元在上一次出現的位置,記為k,則left=k+1(k>=left的前提下)。所以,我們需要乙個陣列,記錄所有元素最後出現的下標,就可以將查詢left的時間從o(n)降到o(1),此時時間複雜度是o(n),空間複雜度是o(1)(增加了長度為256的定長輔助陣列,所以空間複雜度不變)。

實現**如下:

public

class solution

return max;}}

**在leetcode上執行通過。

最樸素的解法,就是遍歷兩個字串的所有子串,然後比較是否相等。兩層巢狀迴圈,再加上字串的比較,時間複雜度是o(m*n*n),其中mn是兩個字串的長度,且m>n。肯定有優化的方法。

考慮使用二維陣列help[i][j],其中istr1的下標,jstr2的下標,help[i][j]記錄的是str1的第i個字元與str2的第j個字元是否相等。舉例說明,字串abccbadeccb,其help陣列為:

很明顯,最長公共子串就是help中對角線上全為1的最長序列,就是圖中的紅色部分。這種解法使用了乙個m*n的輔助陣列,將時間複雜度降到了o(mn)。

其實,help陣列並不需要m*n,只需要n就夠了。如果將help陣列記錄成如下方式:

這樣一來,其實我們在每輪遍歷時,只需要記錄help的一行就可以了,如圖中紅框所示。下一趟遍歷可以覆蓋掉上一趟的結果,只要將有可能是最長的位置記錄下來即可,這裡要使用兩個變數endlengthend記錄help陣列當前的下標,length記錄對應的公共子串的長度。在最後一輪遍歷結束後,只需要返回從end-length+1end的子串,就可以了。

下面是**:

public string getlongestcommonsubstring(string str1, string str2)

}}else

help[j]=0;}}

//get the longest common substring and return it

if(length==0)

return

null;

else

return small.substring(end-length+1,end+1);

}

**在華為oj上測試通過,當然要符合他們的規範。

幾個常見的DP問題及解法

1.求字串的最長不重複子串的長度 舉例 問題分析 記字串存放在字元陣列cs中,遍歷cs的下標為i。分析可知,想求截止到i的最長不重複子串的長度,只要從i向左,找到第1個重複的字元,其右邊的數標記為left,則所求長度就是i left 1與之前求得的結果中的最大值。舉例說明 經分析可知,該演算法需要在...

航空路線問題(dp解法)

從左到右給你n個點,有m條邊連線這些點,問從最左邊的點到達最右邊的點再回到最左邊的點最多可以經過幾個點 除了起點外每個點最多只能被經過一次 首先,我們可以把題意轉化成從最左邊的點走兩條不相交的路線到達最右邊的點,且使經過的點最多。標程是最大費用最大流。為了限流,我們把每個點i拆成兩個點xi,yi,x...

OceanBase幾個常見問題及排查思路

第一種情況 某一台observer掛掉,資料庫異常 oceanbase採用的的是多副本集群模式,在不同的zone裡面有不同的server,每個zone裡面的server是互相備份的。上層是通過slb來分發所以,當其中一台server掛掉的時候,會對業務產生什麼影響呢?製造現象 50使用者併發某查詢交...