迭代与递归
1. 减而治之
例. 数组翻转
迭代方法:
void Reverse(int *A, int low, int high){
while(low < high){
int tmp = A[low];
A[low] = A[high];
A[high] = tmp;
low++;
high--;
}
}
递归方法:
void Reverse(int *A, int low, int high){
if(low >= high)
return;
int tmp = A[low];
A[low] = A[high];
A[high] = tmp;
low++;
high--;
Reverse(A, low, high);
}
2. 分而治之
例1. 总和最大区段
给定任何一个序列 A[0,n), 找出其总和最大区段,如果有多个取最小的那个。
每个数组的“总和最大区段”无非有三种情况:
- 全部落在 [low, middle]
- 全部落在 [middle+1, high]
- 一半落在 [low, middle], 一半落在 [middle+1 , high]
int greatest_sum (int *A, int low, int high){
///left closed and right closed
/// 终止条件
if(low == high)
return A[low];
if(low > high)
return 0;
分治 /
int middle = (low + high) / 2;
左边的最大区段
int greatest_left = 0,sum = 0;
for(int pointer_i = middle; pointer_i >= low; pointer_i--){
sum += A[pointer_i];
if(sum > greatest_left)
greatest_left = sum;
}
右边的最大区段
int greatest_right = 0, sum_right = 0;
for(int pointer_i = middle+1; pointer_i <= high; pointer_i++){
sum_right += A[pointer_i];
if(sum_right > greatest_right)
greatest_right = sum_right;
}
递归:三者取最大
return max(max(greatest_left+greatest_right, greatest_sum(A, middle+1, high)),greatest_sum(A,low,middle));
}
例2. 最长公共子序列
分析:
int lCS(string A, string B, int n, int m){
if(n == -1 or m == -1)
return 0;
if (A[n] == B[m]){
return 1+lCS(A, B, n-1, m-1);
}
if(A[n]!=B[m]){
return max(lCS(A,B,n-1,m),lCS(A,B,n,m-1));
}
}
采用记忆法,来重复利用已经计算过的值,节省运算时间:
int ** dp;
int lCS(string A, string B, int n, int m){
if(n <= 0 or m <= 0)
return 0;
if (A[n] == B[m]){
if(dp[n-1][m-1]!=-100){
// already calculated
return 1 + dp[n-1][m-1];
}
else {
// not calculated
dp[n-1][m-1] = lCS(A, B, n - 1, m - 1);
return 1 + dp[n-1][m-1];
}
}
if(A[n]!=B[m]){
if(dp[n-1][m]==-100) //not in matrix
dp[n-1][m] = lCS(A,B,n-1,m);
if(dp[n][m-1]==-100)
dp[n][m-1] = lCS(A,B,n,m-1);
return max(dp[n-1][m],dp[n][m-1]);
}
}
int main() {
string a = "-educational";
string b = "-advantage";
int n = a.length()-1;
int m = b.length()-1;
dp = new int*[n];
for(int i=0;i<=n;i++){
dp[i] = new int [m];
}
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++){
dp[i][j] = -100;
}
}
cout<<lCS(a,b,n,m);
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++){
cout<<dp[i][j]<<" ";
}
cout<<endl;
}
}