動态程式設計主要用來解決如下技術問題:
- An instance is solved using the solutions for smaller instances;
- 對于一個較小的執行個體,可能需要許多個解決方案;
- 把較小執行個體的解決方案存儲在一個表中,一旦遇上,就很容易解決;
- 附加空間用來節省時間。
上面所列的爬台階問題完全符合這四個屬性,是以,可以使用動态程式設計來解決:
1 2 3 4 5 6 7 8 9 10 11 12 | |
一些基于動态程式設計的算法:
編輯距離
From Wiki:
In computer science, edit distance is a way of quantifying how dissimilar two strings (e.g., words) are to one another by counting the minimum number of operations required to transform one string into the other.
There are three operations permitted on a word: replace, delete, insert. For example, the edit distance between “a” and “b” is 1, the edit distance between “abc” and “def” is 3. This post analyzes how to calculate edit distance by using dynamic programming.
Key Analysis
Let dp[i][j] stands for the edit distance between two strings with length i and j, i.e., word1[0,...,i-1] and word2[0,...,j-1].
There is a relation between dp[i][j] and dp[i-1][j-1]. Let’s say we transform from one string to another. The first string has length i and it’s last character is “x”; the second string has length j and its last character is “y”. The following diagram shows the relation.
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcucmbp1WbhJ3ZvJHctMWatFmb5RWLlNmbhR3cpRWL0lGZl9CXyEzLcNTMwIzLcNHZh9GbwV3LcRnblRnbvNWLwd3Lc12bj5yalVmcj1WYyd2byBnL3d3dvw1LcpDc0RHaiojIsJye.png)
- if x == y, then dp[i][j] == dp[i-1][j-1]
- if x != y, and we insert y for word1, then dp[i][j] = dp[i][j-1] + 1
- if x != y, and we delete x for word1, then dp[i][j] = dp[i-1][j] + 1
- if x != y, and we replace x with y for word1, then dp[i][j] = dp[i-1][j-1] + 1
- When x!=y, dp[i][j] is the min of the three situations.
Initial condition:
dp[i][0] = i, dp[0][j] = j
Java Code
After the analysis above, the code is just a representation of it.
|
最長回文子串 Finding the longest palindromic substring is a classic problem of coding interview. In this post, I will summarize 3 different solutions for this problem.
1. Naive Approach
Naively, we can simply examine every substring and check if it is palindromic. The time complexity is O(n^3). If this is submitted to LeetCode onlinejudge, an error message will be returned – “Time Limit Exceeded”. Therefore, this approach is just a start, we need better algorithm.
|
2. Dynamic Programming
Let s be the input string, i and j are two indices of the string.
Define a 2-dimension array “table” and let table[i][j] denote whether substring from i to j is palindrome.
Start condition:
table[i][i] == 1;
table[i][i+1] == 1 => s.charAt(i) == s.charAt(i+1)
Changing condition:
table[i][j] == 1 => table[i+1][j-1] == 1 && s.charAt(i) == s.charAt(j)
Time O(n^2) Space O(n^2)
|
Given an input, we can use printTable method to examine the table after each iteration. For example, if input string is “dabcba”, the final matrix would be the following:
1 0 0 0 0 0
0 1 0 0 0 1
0 0 1 0 1 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
From the table, we can clear see that the longest string is in cell table[1][5].
3. Simple Algorithm
Time O(n^2), Space O(1)
|
4. Manacher’s Algorithm
Manacher’s algorithm is much more complicated to figure out, even though it will bring benefit of time complexity of O(n).
單詞分割
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = “leetcode”,
dict = ["leet", "code"].
Return true because “leetcode” can be segmented as “leet code”.
1. Naive Approach
This problem can be solve by using a naive approach, which is trivial. A discussion can always start from that though.
|
Time: O(2^n)
2. Dynamic Programming
The key to solve this problem by using dynamic programming approach:
- Define an array t[] such that t[i]==true => 0-(i-1) can be segmented using dictionary
- Initial state t[0] == true
|
Time: O(string length * dict size)
One tricky part of this solution is the case:
INPUT: "programcreek", ["programcree","program","creek"].
最大的子數組
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray [4,−1,2,1] has the largest sum = 6.
Naive Solution
A wrong solution. Simply iterate the array like the following will not work.
|
Dynamic Programming Solution
We should ignore the sum of the previous n-1 elements if nth element is greater than the sum.
public class Solution {
public int maxSubArray(int[] A) {
int max = A[0];
int[] sum = new int[A.length];
sum[0] = A[0];
for (int i = 1; i < A.length; i++) {
sum[i] = Math.max(A[i], sum[i - 1] + A[i]);
max = Math.max(max, sum[i]);
}
return max;
}
}