大多数动态规划问题可以通过两种方式解决:
- 制表:自下而上
- 记忆:自上而下
解决DP中大部分问题的一种更简单的方法是首先编写递归代码,然后编写递归函数的Bottom-up Tabulation Method或Top-down Memoization。编写自顶向下方法解决任何问题的 DP 解决方案的步骤是:
- 编写递归代码
- 记住返回值并使用它来减少递归调用。
一维记忆
第一步是编写递归代码。在下面的程序中,显示了一个与递归相关的程序,其中只有一个参数更改其值。由于只有一个参数是非常量的,所以这种方法被称为一维记忆。例如,在斐波那契数列中找到第 N 项的斐波那契数列问题。这里已经讨论了递归方法。
下面给出的是查找第 N 项的递归代码:
C++
// C++ program to find the Nth term
// of Fibonacci series
#include
using namespace std;
// Fibonacci Series using Recursion
int fib(int n)
{
// Base case
if (n <= 1)
return n;
// recursive calls
return fib(n - 1) + fib(n - 2);
}
// Driver Code
int main()
{
int n = 6;
printf("%d", fib(n));
return 0;
}
Java
// Java program to find the
// Nth term of Fibonacci series
import java.io.*;
class GFG
{
// Fibonacci Series
// using Recursion
static int fib(int n)
{
// Base case
if (n <= 1)
return n;
// recursive calls
return fib(n - 1) +
fib(n - 2);
}
// Driver Code
public static void main (String[] args)
{
int n = 6;
System.out.println(fib(n));
}
}
// This code is contributed
// by ajit
Python3
# Python3 program to find the Nth term
# of Fibonacci series
# Fibonacci Series using Recursion
def fib(n):
# Base case
if (n <= 1):
return n
# recursive calls
return fib(n - 1) + fib(n - 2)
# Driver Code
if __name__=='__main__':
n = 6
print (fib(n))
# This code is contributed by
# Shivi_Aggarwal
C#
// C# program to find
// the Nth term of
// Fibonacci series
using System;
class GFG
{
// Fibonacci Series
// using Recursion
static int fib(int n)
{
// Base case
if (n <= 1)
return n;
// recursive calls
return fib(n - 1) +
fib(n - 2);
}
// Driver Code
static public void Main ()
{
int n = 6;
Console.WriteLine(fib(n));
}
}
// This code is contributed
// by akt_mit
Javascript
PHP
C++
// CPP program to find the Nth term
// of Fibonacci series
#include
using namespace std;
int term[1000];
// Fibonacci Series using memoized Recursion
int fib(int n)
{
// base case
if (n <= 1)
return n;
// if fib(n) has already been computed
// we do not do further recursive calls
// and hence reduce the number of repeated
// work
if (term[n] != 0)
return term[n];
else {
// store the computed value of fib(n)
// in an array term at index n to
// so that it does not needs to be
// precomputed again
term[n] = fib(n - 1) + fib(n - 2);
return term[n];
}
}
// Driver Code
int main()
{
int n = 6;
printf("%d", fib(n));
return 0;
}
Java
// Java program to find
// the Nth term of
// Fibonacci series
import java.io.*;
class GFG
{
static int []term = new int [1000];
// Fibonacci Series using
// memoized Recursion
static int fib(int n)
{
// base case
if (n <= 1)
return n;
// if fib(n) has already
// been computed we do not
// do further recursive
// calls and hence reduce
// the number of repeated
// work
if (term[n] != 0)
return term[n];
else
{
// store the computed value
// of fib(n) in an array
// term at index n to so that
// it does not needs to be
// precomputed again
term[n] = fib(n - 1) +
fib(n - 2);
return term[n];
}
}
// Driver Code
public static void main (String[] args)
{
int n = 6;
System.out.println(fib(n));
}
}
// This code is contributed by ajit
Python3
# Python program to find the Nth term
# of Fibonacci series
term = [0 for i in range(1000)]
# Fibonacci Series using memoized Recursion
def fib(n):
# base case
if n <= 1:
return n
# if fib(n) has already been computed
# we do not do further recursive calls
# and hence reduce the number of repeated
# work
if term[n] != 0:
return term[n]
else:
# store the computed value of fib(n)
# in an array term at index n to
# so that it does not needs to be
# precomputed again
term[n] = fib(n - 1) + fib(n - 2)
return term[n]
# Driver Code
n = 6
print(fib(n))
# This code is contributed by rohitsingh07052
C#
// C# program to find
// the Nth term of
// Fibonacci series
using System;
class GFG
{
// Fibonacci Series using
// memoized Recursion
static int fib(int n)
{
int[] term = new int [1000];
// base case
if (n <= 1)
return n;
// if fib(n) has already
// been computed we do not
// do further recursive
// calls and hence reduce
// the number of repeated
// work
if (term[n] != 0)
return term[n];
else
{
// store the computed value
// of fib(n) in an array
// term at index n to so that
// it does not needs to be
// precomputed again
term[n] = fib(n - 1) +
fib(n - 2);
return term[n];
}
}
// Driver Code
public static void Main ()
{
int n = 6;
Console.Write(fib(n));
}
}
Javascript
C++
// A Naive recursive implementation of LCS problem
#include
int max(int a, int b);
// Returns length of LCS for X[0..m-1], Y[0..n-1]
int lcs(char* X, char* Y, int m, int n)
{
if (m == 0 || n == 0)
return 0;
if (X[m - 1] == Y[n - 1])
return 1 + lcs(X, Y, m - 1, n - 1);
else
return max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
}
// Utility function to get max of 2 integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
int main()
{
char X[] = "AGGTAB";
char Y[] = "GXTXAYB";
int m = strlen(X);
int n = strlen(Y);
printf("Length of LCS is %dn", lcs(X, Y, m, n));
return 0;
}
Java
// A Naive recursive implementation of LCS problem
import java.io.*;
class GFG
{
// Utility function to get max of 2 integers
static int max(int a, int b) { return (a > b) ? a : b; }
// Returns length of LCS for X[0..m-1], Y[0..n-1]
static int lcs(String X, String Y, int m, int n)
{
if (m == 0 || n == 0)
return 0;
if (X.charAt(m - 1) == Y.charAt(n - 1))
return 1 + lcs(X, Y, m - 1, n - 1);
else
return max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
}
// Driver Code
public static void main(String[] args)
{
String X = "AGGTAB";
String Y = "GXTXAYB";
int m = X.length();
int n = Y.length();
System.out.print("Length of LCS is "
+ lcs(X, Y, m, n));
}
}
// This code is contributed by subhammahato348
Python3
# A Naive recursive implementation of LCS problem
# Returns length of LCS for X[0..m-1], Y[0..n-1]
def lcs(X, Y, m, n):
if (m == 0 or n == 0):
return 0;
if (X[m - 1] == Y[n - 1]):
return 1 + lcs(X, Y, m - 1, n - 1);
else:
return max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
# Driver Code
if __name__=='__main__':
X = "AGGTAB";
Y = "GXTXAYB";
m = len(X);
n = len(Y);
print("Length of LCS is {}n".format(lcs(X, Y, m, n)))
# This code is contributed by rutvik_56.
C#
// A Naive recursive implementation of LCS problem
using System;
class GFG
{
// Utility function to get max of 2 integers
static int max(int a, int b) { return (a > b) ? a : b; }
// Returns length of LCS for X[0..m-1], Y[0..n-1]
static int lcs(string X, string Y, int m, int n)
{
if (m == 0 || n == 0)
return 0;
if (X[m - 1] == Y[n - 1])
return 1 + lcs(X, Y, m - 1, n - 1);
else
return max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
}
// Driver Code
public static void Main()
{
string X = "AGGTAB";
string Y = "GXTXAYB";
int m = X.Length;
int n = Y.Length;
Console.Write("Length of LCS is "
+ lcs(X, Y, m, n));
}
}
// This code is contributed by subhammahato348
Javascript
C++
// C++ program to memoize
// recursive implementation of LCS problem
#include
int arr[1000][1000];
int max(int a, int b);
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
int lcs(char* X, char* Y, int m, int n)
{
// base case
if (m == 0 || n == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1][n - 1] != -1)
return arr[m - 1][n - 1];
// if equal, then we store the value of the
// function call
if (X[m - 1] == Y[n - 1]) {
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1][n - 1] = 1 + lcs(X, Y, m - 1, n - 1);
return arr[m - 1][n - 1];
}
else {
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1][n - 1] = max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
return arr[m - 1][n - 1];
}
}
// Utility function to get max of 2 integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
int main()
{
memset(arr, -1, sizeof(arr));
char X[] = "AGGTAB";
char Y[] = "GXTXAYB";
int m = strlen(X);
int n = strlen(Y);
printf("Length of LCS is %d", lcs(X, Y, m, n));
return 0;
}
Java
// Java program to memoize
// recursive implementation of LCS problem
import java.io.*;
import java.lang.*;
class GFG
{
public static int arr[][] = new int[1000][1000];
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
public static int lcs(String X, String Y, int m, int n)
{
// base case
if (m == 0 || n == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1][n - 1] != -1)
return arr[m - 1][n - 1];
// if equal, then we store the value of the
// function call
if ( X.charAt(m - 1) == Y.charAt(n - 1))
{
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1][n - 1] = 1 + lcs(X, Y, m - 1, n - 1);
return arr[m - 1][n - 1];
}
else
{
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1][n - 1] = max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
return arr[m - 1][n - 1];
}
}
// Utility function to get max of 2 integers
public static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver code
public static void main (String[] args)
{
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
{
arr[i][j] = -1;
}
}
String X = "AGGTAB";
String Y = "GXTXAYB";
int m = X.length();
int n = Y.length();
System.out.println("Length of LCS is " + lcs(X, Y, m, n));
}
}
// This code is contributed by manupathria.
Python3
# Python3 program to memoize
# recursive implementation of LCS problem
# Returns length of LCS for X[0..m-1], Y[0..n-1]
# memoization applied in recursive solution
def lcs(X, Y, m, n):
global arr
# base case
if (m == 0 or n == 0):
return 0
# if the same state has already been
# computed
if (arr[m - 1][n - 1] != -1):
return arr[m - 1][n - 1]
# if equal, then we store the value of the
# function call
if (X[m - 1] == Y[n - 1]):
# store it in arr to avoid further repetitive
# work in future function calls
arr[m - 1][n - 1] = 1 + lcs(X, Y, m - 1, n - 1)
return arr[m - 1][n - 1]
else:
# store it in arr to avoid further repetitive
# work in future function calls
arr[m - 1][n - 1] = max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n))
return arr[m - 1][n - 1]
# Driver code
arr = [[0]*1000]*1000
for i in range(0, 1000):
for j in range(0, 1000):
arr[i][j] = -1
X = "AGGTAB"
Y = "GXTXAYB"
m = len(X)
n = len(Y)
print("Length of LCS is ", lcs(X, Y, m, n))
# This code is contributed by Dharanendra L V.
C#
// C# program to memoize
// recursive implementation of LCS problem
using System;
public class GFG
{
public static int[, ] arr = new int[1000, 1000];
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
public static int lcs(String X, String Y, int m, int n)
{
// base case
if (m == 0 || n == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1, n - 1] != -1)
return arr[m - 1, n - 1];
// if equal, then we store the value of the
// function call
if ( X[m - 1] == Y[n - 1])
{
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1, n - 1] = 1 + lcs(X, Y, m - 1, n - 1);
return arr[m - 1, n - 1];
}
else
{
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1, n - 1] = max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
return arr[m - 1, n - 1];
}
}
// Utility function to get max of 2 integers
public static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver code
static public void Main (){
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
{
arr[i, j] = -1;
}
}
String X = "AGGTAB";
String Y = "GXTXAYB";
int m = X.Length;
int n = Y.Length;
Console.WriteLine("Length of LCS is " + lcs(X, Y, m, n));
}
}
// This code is contributed by Dharanendra L V.
Javascript
C++
// A recursive implementation of LCS problem
// of three strings
#include
int max(int a, int b);
// Returns length of LCS for X[0..m-1], Y[0..n-1]
int lcs(char* X, char* Y, char* Z, int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if equal, then check for next combination
if (X[m - 1] == Y[n - 1] and Y[n - 1] == Z[o - 1]) {
// recursive call
return 1 + lcs(X, Y, Z, m - 1, n - 1, o - 1);
}
else {
// return the maximum of the three other
// possible states in recursion
return max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
}
}
// Utility function to get max of 2 integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
int main()
{
char X[] = "geeks";
char Y[] = "geeksfor";
char Z[] = "geeksforge";
int m = strlen(X);
int n = strlen(Y);
int o = strlen(Z);
printf("Length of LCS is %d", lcs(X, Y, Z, m, n, o));
return 0;
}
Java
// A recursive implementation of LCS problem
// of three strings
class GFG
{
// Utility function to get max of 2 integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns length of LCS for X[0..m-1], Y[0..n-1]
static int lcs(char[] X, char[] Y, char[] Z,
int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if equal, then check for next combination
if (X[m - 1] == Y[n - 1] && Y[n - 1] == Z[o - 1])
{
// recursive call
return 1 + lcs(X, Y, Z, m - 1, n - 1, o - 1);
}
else
{
// return the maximum of the three other
// possible states in recursion
return Math.max(lcs(X, Y, Z, m, n - 1, o),
Math.max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
}
}
// Driver code
public static void main(String[] args)
{
char[] X = "geeks".toCharArray();
char[] Y = "geeksfor".toCharArray();
char[] Z = "geeksforge".toCharArray();
int m = X.length;
int n = Y.length;
int o = Z.length;
System.out.println("Length of LCS is " + lcs(X, Y, Z, m, n, o));
}
}
// This code is contributed by divyesh072019.
C#
// A recursive implementation of LCS problem
// of three strings
using System;
class GFG {
// Utility function to get max of 2 integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns length of LCS for X[0..m-1], Y[0..n-1]
static int lcs(char[] X, char[] Y, char[] Z, int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if equal, then check for next combination
if (X[m - 1] == Y[n - 1] && Y[n - 1] == Z[o - 1])
{
// recursive call
return 1 + lcs(X, Y, Z, m - 1, n - 1, o - 1);
}
else
{
// return the maximum of the three other
// possible states in recursion
return Math.Max(lcs(X, Y, Z, m, n - 1, o),
Math.Max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
}
}
// Driver code
static void Main()
{
char[] X = "geeks".ToCharArray();
char[] Y = "geeksfor".ToCharArray();
char[] Z = "geeksforge".ToCharArray();
int m = X.Length;
int n = Y.Length;
int o = Z.Length;
Console.WriteLine("Length of LCS is " + lcs(X, Y, Z, m, n, o));
}
}
// This code is contributed by divyeshrabadiya07
Javascript
C++
// A memoize recursive implementation of LCS problem
#include
int arr[100][100][100];
int max(int a, int b);
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
int lcs(char* X, char* Y, char* Z, int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1][n - 1][o - 1] != -1)
return arr[m - 1][n - 1][o - 1];
// if equal, then we store the value of the
// function call
if (X[m - 1] == Y[n - 1] and Y[n - 1] == Z[o - 1]) {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1][n - 1][o - 1] = 1 + lcs(X, Y, Z, m - 1,
n - 1, o - 1);
return arr[m - 1][n - 1][o - 1];
}
else {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1][n - 1][o - 1] =
max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
return arr[m - 1][n - 1][o - 1];
}
}
// Utility function to get max of 2 integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
int main()
{
memset(arr, -1, sizeof(arr));
char X[] = "geeks";
char Y[] = "geeksfor";
char Z[] = "geeksforgeeks";
int m = strlen(X);
int n = strlen(Y);
int o = strlen(Z);
printf("Length of LCS is %d", lcs(X, Y, Z, m, n, o));
return 0;
}
Java
// A memoize recursive implementation of LCS problem
import java.io.*;
class GFG
{
public static int[][][] arr = new int[100][100][100];
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
static int lcs(String X, String Y, String Z,
int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1][n - 1][o - 1] != -1)
return arr[m - 1][n - 1][o - 1];
// if equal, then we store the value of the
// function call
if (X.charAt(m - 1) == Y.charAt(n - 1) &&
Y.charAt(n - 1) == Z.charAt(o - 1)) {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1][n - 1][o - 1] = 1 + lcs(X, Y, Z, m - 1,
n - 1, o - 1);
return arr[m - 1][n - 1][o - 1];
}
else
{
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1][n - 1][o - 1] =
max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
return arr[m - 1][n - 1][o - 1];
}
}
// Utility function to get max of 2 integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
public static void main (String[] args)
{
for(int i = 0; i < 100; i++)
{
for(int j = 0; j < 100; j++)
{
for(int k = 0; k < 100; k++)
{
arr[i][j][k] = -1;
}
}
}
String X = "geeks";
String Y = "geeksfor";
String Z = "geeksforgeeks";
int m = X.length();
int n = Y.length();
int o = Z.length();
System.out.print("Length of LCS is " + lcs(X, Y, Z, m, n, o));
}
}
// This code is contributed by Dharanendra L V.
Python3
# A memoize recursive implementation of LCS problem
# Returns length of LCS for X[0..m-1], Y[0..n-1] */
# memoization applied in recursive solution
def lcs(X, Y, Z, m, n, o):
global arr
# base case
if(m == 0 or n == 0 or o == 0):
return 0
# if the same state has already been
# computed
if (arr[m - 1][n - 1][o - 1] != -1):
return arr[m - 1][n - 1][o - 1]
# if equal, then we store the value of the
# function call
if (X[m - 1] == Y[n - 1] and
Y[n - 1] == Z[o - 1]):
# store it in arr to avoid further repetitive work
# in future function calls
arr[m - 1][n - 1][o - 1] = 1 + lcs(X, Y, Z, m - 1,
n - 1, o - 1)
return arr[m - 1][n - 1][o - 1]
else:
# store it in arr to avoid further repetitive work
# in future function calls
arr[m - 1][n - 1][o - 1] = max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o), lcs(X, Y, Z, m, n, o - 1)))
return arr[m - 1][n - 1][o - 1]
# Driver Code
arr = [[[0 for k in range(100)] for j in range(100)] for i in range(100)]
for i in range(100):
for j in range(100):
for k in range(100):
arr[i][j][k] = -1
X = "geeks"
Y = "geeksfor"
Z = "geeksforgeeks"
m = len(X)
n = len(Y)
o = len(Z)
print("Length of LCS is ", lcs(X, Y, Z, m, n, o))
# This code is contributed by Dharanendra L V.
C#
// A memoize recursive implementation of LCS problem
using System;
public class GFG{
public static int[, , ] arr = new int[100, 100, 100];
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
static int lcs(String X, String Y, String Z, int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1, n - 1, o - 1] != -1)
return arr[m - 1, n - 1, o - 1];
// if equal, then we store the value of the
// function call
if (X[m - 1] == Y[n - 1] &&
Y[n - 1] == Z[o - 1]) {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1, n - 1, o - 1] = 1 + lcs(X, Y, Z, m - 1,
n - 1, o - 1);
return arr[m - 1, n - 1, o - 1];
}
else {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1, n - 1, o - 1] =
max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
return arr[m - 1, n - 1, o - 1];
}
}
// Utility function to get max of 2 integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
static public void Main (){
for(int i = 0; i < 100; i++) {
for(int j = 0; j < 100; j++) {
for(int k = 0; k < 100; k++) {
arr[i, j, k] = -1;
}
}
}
String X = "geeks";
String Y = "geeksfor";
String Z = "geeksforgeeks";
int m = X.Length;
int n = Y.Length;
int o = Z.Length;
Console.WriteLine("Length of LCS is " + lcs(X, Y, Z, m, n, o));
}
}
// This code is contributed by Dharanendra L V.
Javascript
8
一个常见的观察是这个实现做了很多重复的工作(见下面的递归树)。因此,如果完成,这将花费大量时间来查找第 N 个斐波那契数。
fib(5)
/ \
fib(4) fib(3)
/ \ / \
fib(3) fib(2) fib(2) fib(1)
/ \ / \ / \
fib(2) fib(1) fib(1) fib(0) fib(1) fib(0)
/ \
fib(1) fib(0)
In the above tree fib(3), fib(2), fib(1), fib(0) all are called more then once.
以下问题已使用制表方法解决。
在下面的程序中,已经解释了编写自上而下方法程序的步骤。递归程序中的一些修改将降低程序的复杂性并给出所需的结果。如果 fib(x) 之前没有发生,那么我们将fib(x)的值存储在索引 x 处的数组 term 中并返回 term[x] 。通过在数组的索引 x 处记住 fib(x) 的返回值,当 fib(x) 已经被调用时,减少下一步的递归调用次数。因此,无需进一步递归调用来计算 fib(x) 的值,如果之前已经计算过 fib(x) ,则返回 term[x]以避免树中所示的大量重复工作。
下面给出的是找到第 N 项的记忆递归代码。
C++
// CPP program to find the Nth term
// of Fibonacci series
#include
using namespace std;
int term[1000];
// Fibonacci Series using memoized Recursion
int fib(int n)
{
// base case
if (n <= 1)
return n;
// if fib(n) has already been computed
// we do not do further recursive calls
// and hence reduce the number of repeated
// work
if (term[n] != 0)
return term[n];
else {
// store the computed value of fib(n)
// in an array term at index n to
// so that it does not needs to be
// precomputed again
term[n] = fib(n - 1) + fib(n - 2);
return term[n];
}
}
// Driver Code
int main()
{
int n = 6;
printf("%d", fib(n));
return 0;
}
Java
// Java program to find
// the Nth term of
// Fibonacci series
import java.io.*;
class GFG
{
static int []term = new int [1000];
// Fibonacci Series using
// memoized Recursion
static int fib(int n)
{
// base case
if (n <= 1)
return n;
// if fib(n) has already
// been computed we do not
// do further recursive
// calls and hence reduce
// the number of repeated
// work
if (term[n] != 0)
return term[n];
else
{
// store the computed value
// of fib(n) in an array
// term at index n to so that
// it does not needs to be
// precomputed again
term[n] = fib(n - 1) +
fib(n - 2);
return term[n];
}
}
// Driver Code
public static void main (String[] args)
{
int n = 6;
System.out.println(fib(n));
}
}
// This code is contributed by ajit
蟒蛇3
# Python program to find the Nth term
# of Fibonacci series
term = [0 for i in range(1000)]
# Fibonacci Series using memoized Recursion
def fib(n):
# base case
if n <= 1:
return n
# if fib(n) has already been computed
# we do not do further recursive calls
# and hence reduce the number of repeated
# work
if term[n] != 0:
return term[n]
else:
# store the computed value of fib(n)
# in an array term at index n to
# so that it does not needs to be
# precomputed again
term[n] = fib(n - 1) + fib(n - 2)
return term[n]
# Driver Code
n = 6
print(fib(n))
# This code is contributed by rohitsingh07052
C#
// C# program to find
// the Nth term of
// Fibonacci series
using System;
class GFG
{
// Fibonacci Series using
// memoized Recursion
static int fib(int n)
{
int[] term = new int [1000];
// base case
if (n <= 1)
return n;
// if fib(n) has already
// been computed we do not
// do further recursive
// calls and hence reduce
// the number of repeated
// work
if (term[n] != 0)
return term[n];
else
{
// store the computed value
// of fib(n) in an array
// term at index n to so that
// it does not needs to be
// precomputed again
term[n] = fib(n - 1) +
fib(n - 2);
return term[n];
}
}
// Driver Code
public static void Main ()
{
int n = 6;
Console.Write(fib(n));
}
}
Javascript
8
如果递归代码已经写过一次,那么记忆只是修改递归程序并存储返回值以避免重复调用先前计算过的函数。
二维记忆
在上面的程序中,递归函数只有一个参数,其值在每次函数调用后都不是常量。下面显示了递归程序具有两个非常量参数的实现。
例如,当给出两个字符串时,用于解决标准动态问题 LCS 问题的程序。该问题的一般递归解决方案是生成两个给定序列的所有子序列,并找到最长的匹配子序列。可能的组合总数为 2 n 。因此,递归解决方案将需要O(2 n ) 。此处讨论了编写递归解决方案的方法。
下面给出了 LCS 问题的递归解决方案:
C++
// A Naive recursive implementation of LCS problem
#include
int max(int a, int b);
// Returns length of LCS for X[0..m-1], Y[0..n-1]
int lcs(char* X, char* Y, int m, int n)
{
if (m == 0 || n == 0)
return 0;
if (X[m - 1] == Y[n - 1])
return 1 + lcs(X, Y, m - 1, n - 1);
else
return max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
}
// Utility function to get max of 2 integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
int main()
{
char X[] = "AGGTAB";
char Y[] = "GXTXAYB";
int m = strlen(X);
int n = strlen(Y);
printf("Length of LCS is %dn", lcs(X, Y, m, n));
return 0;
}
Java
// A Naive recursive implementation of LCS problem
import java.io.*;
class GFG
{
// Utility function to get max of 2 integers
static int max(int a, int b) { return (a > b) ? a : b; }
// Returns length of LCS for X[0..m-1], Y[0..n-1]
static int lcs(String X, String Y, int m, int n)
{
if (m == 0 || n == 0)
return 0;
if (X.charAt(m - 1) == Y.charAt(n - 1))
return 1 + lcs(X, Y, m - 1, n - 1);
else
return max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
}
// Driver Code
public static void main(String[] args)
{
String X = "AGGTAB";
String Y = "GXTXAYB";
int m = X.length();
int n = Y.length();
System.out.print("Length of LCS is "
+ lcs(X, Y, m, n));
}
}
// This code is contributed by subhammahato348
蟒蛇3
# A Naive recursive implementation of LCS problem
# Returns length of LCS for X[0..m-1], Y[0..n-1]
def lcs(X, Y, m, n):
if (m == 0 or n == 0):
return 0;
if (X[m - 1] == Y[n - 1]):
return 1 + lcs(X, Y, m - 1, n - 1);
else:
return max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
# Driver Code
if __name__=='__main__':
X = "AGGTAB";
Y = "GXTXAYB";
m = len(X);
n = len(Y);
print("Length of LCS is {}n".format(lcs(X, Y, m, n)))
# This code is contributed by rutvik_56.
C#
// A Naive recursive implementation of LCS problem
using System;
class GFG
{
// Utility function to get max of 2 integers
static int max(int a, int b) { return (a > b) ? a : b; }
// Returns length of LCS for X[0..m-1], Y[0..n-1]
static int lcs(string X, string Y, int m, int n)
{
if (m == 0 || n == 0)
return 0;
if (X[m - 1] == Y[n - 1])
return 1 + lcs(X, Y, m - 1, n - 1);
else
return max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
}
// Driver Code
public static void Main()
{
string X = "AGGTAB";
string Y = "GXTXAYB";
int m = X.Length;
int n = Y.Length;
Console.Write("Length of LCS is "
+ lcs(X, Y, m, n));
}
}
// This code is contributed by subhammahato348
Javascript
输出:
Length of LCS is 4
考虑到上面的实现,下面是输入字符串“AXYT”和“AYZX”的部分递归树
lcs("AXYT", "AYZX")
/ \
lcs("AXY", "AYZX") lcs("AXYT", "AYZ")
/ \ / \
lcs("AX", "AYZX") lcs("AXY", "AYZ") lcs("AXY", "AYZ") lcs("AXYT", "AY")
在上面的部分递归树中, lcs(“AXY”, “AYZ”) 被求解了两次。在绘制完整的递归树时,已经观察到有许多子问题被一次又一次地解决。所以这个问题具有重叠子结构的性质,并且可以通过使用 Memoization 或 Tabulation 来避免相同子问题的重新计算。这里已经讨论了制表方法。
在递归代码中使用记忆化的一个常见观察点是每个函数调用中的两个非常量参数 M 和 N。该函数有 4 个参数,但 2 个参数是常量,不影响记忆。重复调用发生在之前调用过的 N 和 M 上。因此,使用2-d阵列所计算的LCS(M,N)值存储在ARR [M-1] [N-1]从0字符串索引开始每当使用相同的参数米的函数和n被称为再次,我们不执行任何进一步的递归调用并返回 arr[m-1][n-1] 因为之前的 lcs(m, n) 计算已经存储在 arr[m-1][n-1] ],因此减少了不止一次发生的递归调用。
下面是递归代码的 Memoization 方法的实现。
C++
// C++ program to memoize
// recursive implementation of LCS problem
#include
int arr[1000][1000];
int max(int a, int b);
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
int lcs(char* X, char* Y, int m, int n)
{
// base case
if (m == 0 || n == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1][n - 1] != -1)
return arr[m - 1][n - 1];
// if equal, then we store the value of the
// function call
if (X[m - 1] == Y[n - 1]) {
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1][n - 1] = 1 + lcs(X, Y, m - 1, n - 1);
return arr[m - 1][n - 1];
}
else {
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1][n - 1] = max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
return arr[m - 1][n - 1];
}
}
// Utility function to get max of 2 integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
int main()
{
memset(arr, -1, sizeof(arr));
char X[] = "AGGTAB";
char Y[] = "GXTXAYB";
int m = strlen(X);
int n = strlen(Y);
printf("Length of LCS is %d", lcs(X, Y, m, n));
return 0;
}
Java
// Java program to memoize
// recursive implementation of LCS problem
import java.io.*;
import java.lang.*;
class GFG
{
public static int arr[][] = new int[1000][1000];
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
public static int lcs(String X, String Y, int m, int n)
{
// base case
if (m == 0 || n == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1][n - 1] != -1)
return arr[m - 1][n - 1];
// if equal, then we store the value of the
// function call
if ( X.charAt(m - 1) == Y.charAt(n - 1))
{
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1][n - 1] = 1 + lcs(X, Y, m - 1, n - 1);
return arr[m - 1][n - 1];
}
else
{
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1][n - 1] = max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
return arr[m - 1][n - 1];
}
}
// Utility function to get max of 2 integers
public static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver code
public static void main (String[] args)
{
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
{
arr[i][j] = -1;
}
}
String X = "AGGTAB";
String Y = "GXTXAYB";
int m = X.length();
int n = Y.length();
System.out.println("Length of LCS is " + lcs(X, Y, m, n));
}
}
// This code is contributed by manupathria.
蟒蛇3
# Python3 program to memoize
# recursive implementation of LCS problem
# Returns length of LCS for X[0..m-1], Y[0..n-1]
# memoization applied in recursive solution
def lcs(X, Y, m, n):
global arr
# base case
if (m == 0 or n == 0):
return 0
# if the same state has already been
# computed
if (arr[m - 1][n - 1] != -1):
return arr[m - 1][n - 1]
# if equal, then we store the value of the
# function call
if (X[m - 1] == Y[n - 1]):
# store it in arr to avoid further repetitive
# work in future function calls
arr[m - 1][n - 1] = 1 + lcs(X, Y, m - 1, n - 1)
return arr[m - 1][n - 1]
else:
# store it in arr to avoid further repetitive
# work in future function calls
arr[m - 1][n - 1] = max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n))
return arr[m - 1][n - 1]
# Driver code
arr = [[0]*1000]*1000
for i in range(0, 1000):
for j in range(0, 1000):
arr[i][j] = -1
X = "AGGTAB"
Y = "GXTXAYB"
m = len(X)
n = len(Y)
print("Length of LCS is ", lcs(X, Y, m, n))
# This code is contributed by Dharanendra L V.
C#
// C# program to memoize
// recursive implementation of LCS problem
using System;
public class GFG
{
public static int[, ] arr = new int[1000, 1000];
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
public static int lcs(String X, String Y, int m, int n)
{
// base case
if (m == 0 || n == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1, n - 1] != -1)
return arr[m - 1, n - 1];
// if equal, then we store the value of the
// function call
if ( X[m - 1] == Y[n - 1])
{
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1, n - 1] = 1 + lcs(X, Y, m - 1, n - 1);
return arr[m - 1, n - 1];
}
else
{
// store it in arr to avoid further repetitive
// work in future function calls
arr[m - 1, n - 1] = max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
return arr[m - 1, n - 1];
}
}
// Utility function to get max of 2 integers
public static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver code
static public void Main (){
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
{
arr[i, j] = -1;
}
}
String X = "AGGTAB";
String Y = "GXTXAYB";
int m = X.Length;
int n = Y.Length;
Console.WriteLine("Length of LCS is " + lcs(X, Y, m, n));
}
}
// This code is contributed by Dharanendra L V.
Javascript
Length of LCS is 4
3D 记忆
在上面的程序中,递归函数只有两个参数,它们的值在每次函数调用后都不是常量。下面,完成了递归程序具有三个非常量参数的实现。
例如,用于解决三个字符串的标准动态问题 LCS 问题的程序。该问题的一般递归解决方案是生成两个给定序列的所有子序列,并找到最长的匹配子序列。可能的组合总数为 3 n 。因此,递归解决方案将需要O(3 n ) 。
下面给出了 LCS 问题的递归解决方案:
C++
// A recursive implementation of LCS problem
// of three strings
#include
int max(int a, int b);
// Returns length of LCS for X[0..m-1], Y[0..n-1]
int lcs(char* X, char* Y, char* Z, int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if equal, then check for next combination
if (X[m - 1] == Y[n - 1] and Y[n - 1] == Z[o - 1]) {
// recursive call
return 1 + lcs(X, Y, Z, m - 1, n - 1, o - 1);
}
else {
// return the maximum of the three other
// possible states in recursion
return max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
}
}
// Utility function to get max of 2 integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
int main()
{
char X[] = "geeks";
char Y[] = "geeksfor";
char Z[] = "geeksforge";
int m = strlen(X);
int n = strlen(Y);
int o = strlen(Z);
printf("Length of LCS is %d", lcs(X, Y, Z, m, n, o));
return 0;
}
Java
// A recursive implementation of LCS problem
// of three strings
class GFG
{
// Utility function to get max of 2 integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns length of LCS for X[0..m-1], Y[0..n-1]
static int lcs(char[] X, char[] Y, char[] Z,
int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if equal, then check for next combination
if (X[m - 1] == Y[n - 1] && Y[n - 1] == Z[o - 1])
{
// recursive call
return 1 + lcs(X, Y, Z, m - 1, n - 1, o - 1);
}
else
{
// return the maximum of the three other
// possible states in recursion
return Math.max(lcs(X, Y, Z, m, n - 1, o),
Math.max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
}
}
// Driver code
public static void main(String[] args)
{
char[] X = "geeks".toCharArray();
char[] Y = "geeksfor".toCharArray();
char[] Z = "geeksforge".toCharArray();
int m = X.length;
int n = Y.length;
int o = Z.length;
System.out.println("Length of LCS is " + lcs(X, Y, Z, m, n, o));
}
}
// This code is contributed by divyesh072019.
C#
// A recursive implementation of LCS problem
// of three strings
using System;
class GFG {
// Utility function to get max of 2 integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns length of LCS for X[0..m-1], Y[0..n-1]
static int lcs(char[] X, char[] Y, char[] Z, int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if equal, then check for next combination
if (X[m - 1] == Y[n - 1] && Y[n - 1] == Z[o - 1])
{
// recursive call
return 1 + lcs(X, Y, Z, m - 1, n - 1, o - 1);
}
else
{
// return the maximum of the three other
// possible states in recursion
return Math.Max(lcs(X, Y, Z, m, n - 1, o),
Math.Max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
}
}
// Driver code
static void Main()
{
char[] X = "geeks".ToCharArray();
char[] Y = "geeksfor".ToCharArray();
char[] Z = "geeksforge".ToCharArray();
int m = X.Length;
int n = Y.Length;
int o = Z.Length;
Console.WriteLine("Length of LCS is " + lcs(X, Y, Z, m, n, o));
}
}
// This code is contributed by divyeshrabadiya07
Javascript
Length of LCS is 5
此处显示了制表方法。在完整绘制递归树时,注意到有许多重叠的子问题被多次计算。由于函数参数具有三个非常量参数,因此将使用一个 3-D 数组来记忆当lcs(x, y, z, m, n, o)为 m, n, 的任何值时返回的值,并且 o 被调用,以便如果再次调用lcs(x, y, z, m, n, o)以获取相同的 m、n 和 o 值,则该函数将返回先前已计算的已存储值在递归调用中。 arr[m][n][o] 存储lcs(x, y, z, m, n, o)函数调用返回的值。递归程序中唯一需要做的修改是存储递归函数的(m,n,o)状态的返回值。其余的在上述递归程序中保持不变。
下面是递归代码的 Memoization 方法的实现:
C++
// A memoize recursive implementation of LCS problem
#include
int arr[100][100][100];
int max(int a, int b);
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
int lcs(char* X, char* Y, char* Z, int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1][n - 1][o - 1] != -1)
return arr[m - 1][n - 1][o - 1];
// if equal, then we store the value of the
// function call
if (X[m - 1] == Y[n - 1] and Y[n - 1] == Z[o - 1]) {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1][n - 1][o - 1] = 1 + lcs(X, Y, Z, m - 1,
n - 1, o - 1);
return arr[m - 1][n - 1][o - 1];
}
else {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1][n - 1][o - 1] =
max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
return arr[m - 1][n - 1][o - 1];
}
}
// Utility function to get max of 2 integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
int main()
{
memset(arr, -1, sizeof(arr));
char X[] = "geeks";
char Y[] = "geeksfor";
char Z[] = "geeksforgeeks";
int m = strlen(X);
int n = strlen(Y);
int o = strlen(Z);
printf("Length of LCS is %d", lcs(X, Y, Z, m, n, o));
return 0;
}
Java
// A memoize recursive implementation of LCS problem
import java.io.*;
class GFG
{
public static int[][][] arr = new int[100][100][100];
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
static int lcs(String X, String Y, String Z,
int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1][n - 1][o - 1] != -1)
return arr[m - 1][n - 1][o - 1];
// if equal, then we store the value of the
// function call
if (X.charAt(m - 1) == Y.charAt(n - 1) &&
Y.charAt(n - 1) == Z.charAt(o - 1)) {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1][n - 1][o - 1] = 1 + lcs(X, Y, Z, m - 1,
n - 1, o - 1);
return arr[m - 1][n - 1][o - 1];
}
else
{
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1][n - 1][o - 1] =
max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
return arr[m - 1][n - 1][o - 1];
}
}
// Utility function to get max of 2 integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
public static void main (String[] args)
{
for(int i = 0; i < 100; i++)
{
for(int j = 0; j < 100; j++)
{
for(int k = 0; k < 100; k++)
{
arr[i][j][k] = -1;
}
}
}
String X = "geeks";
String Y = "geeksfor";
String Z = "geeksforgeeks";
int m = X.length();
int n = Y.length();
int o = Z.length();
System.out.print("Length of LCS is " + lcs(X, Y, Z, m, n, o));
}
}
// This code is contributed by Dharanendra L V.
蟒蛇3
# A memoize recursive implementation of LCS problem
# Returns length of LCS for X[0..m-1], Y[0..n-1] */
# memoization applied in recursive solution
def lcs(X, Y, Z, m, n, o):
global arr
# base case
if(m == 0 or n == 0 or o == 0):
return 0
# if the same state has already been
# computed
if (arr[m - 1][n - 1][o - 1] != -1):
return arr[m - 1][n - 1][o - 1]
# if equal, then we store the value of the
# function call
if (X[m - 1] == Y[n - 1] and
Y[n - 1] == Z[o - 1]):
# store it in arr to avoid further repetitive work
# in future function calls
arr[m - 1][n - 1][o - 1] = 1 + lcs(X, Y, Z, m - 1,
n - 1, o - 1)
return arr[m - 1][n - 1][o - 1]
else:
# store it in arr to avoid further repetitive work
# in future function calls
arr[m - 1][n - 1][o - 1] = max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o), lcs(X, Y, Z, m, n, o - 1)))
return arr[m - 1][n - 1][o - 1]
# Driver Code
arr = [[[0 for k in range(100)] for j in range(100)] for i in range(100)]
for i in range(100):
for j in range(100):
for k in range(100):
arr[i][j][k] = -1
X = "geeks"
Y = "geeksfor"
Z = "geeksforgeeks"
m = len(X)
n = len(Y)
o = len(Z)
print("Length of LCS is ", lcs(X, Y, Z, m, n, o))
# This code is contributed by Dharanendra L V.
C#
// A memoize recursive implementation of LCS problem
using System;
public class GFG{
public static int[, , ] arr = new int[100, 100, 100];
// Returns length of LCS for X[0..m-1], Y[0..n-1] */
// memoization applied in recursive solution
static int lcs(String X, String Y, String Z, int m, int n, int o)
{
// base case
if (m == 0 || n == 0 || o == 0)
return 0;
// if the same state has already been
// computed
if (arr[m - 1, n - 1, o - 1] != -1)
return arr[m - 1, n - 1, o - 1];
// if equal, then we store the value of the
// function call
if (X[m - 1] == Y[n - 1] &&
Y[n - 1] == Z[o - 1]) {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1, n - 1, o - 1] = 1 + lcs(X, Y, Z, m - 1,
n - 1, o - 1);
return arr[m - 1, n - 1, o - 1];
}
else {
// store it in arr to avoid further repetitive work
// in future function calls
arr[m - 1, n - 1, o - 1] =
max(lcs(X, Y, Z, m, n - 1, o),
max(lcs(X, Y, Z, m - 1, n, o),
lcs(X, Y, Z, m, n, o - 1)));
return arr[m - 1, n - 1, o - 1];
}
}
// Utility function to get max of 2 integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Driver Code
static public void Main (){
for(int i = 0; i < 100; i++) {
for(int j = 0; j < 100; j++) {
for(int k = 0; k < 100; k++) {
arr[i, j, k] = -1;
}
}
}
String X = "geeks";
String Y = "geeksfor";
String Z = "geeksforgeeks";
int m = X.Length;
int n = Y.Length;
int o = Z.Length;
Console.WriteLine("Length of LCS is " + lcs(X, Y, Z, m, n, o));
}
}
// This code is contributed by Dharanendra L V.
Javascript
Length of LCS is 5
注意:用于 Memoize 的数组在函数调用之前被初始化为某个值(比如 -1),以标记具有相同参数的函数是否已被调用过。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。