Skip to content

Commit 2d4a932

Browse files
committed
Add longest-common-subsequence solution
1 parent e7bd5c1 commit 2d4a932

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* @param {string} text1
3+
* @param {string} text2
4+
* @return {number}
5+
*/
6+
7+
// 🤔
8+
// Both memoization (top-down) and dynamic programming (bottom-up) have the same time and space complexity of O(m * n).
9+
// The difference lies in their implementation:
10+
// - Memoization uses recursion with a cache to avoid redundant calculations but may incur overhead from recursive calls and stack space.
11+
// - Dynamic Programming iteratively builds the solution, avoiding recursion overhead and sometimes offering better performance.
12+
// DP is often preferred when recursion depth or function call overhead is a concern, while memoization can be more intuitive for certain problems.
13+
14+
// 😊 memoization approach
15+
// Time Complexity: O(m * n), where m is the length of text1, and n is the length of text2
16+
// Space Complexity: O(m * n)
17+
// Top-down approach with recursion.
18+
// Use a cache (or memoization) to store intermediate results.
19+
20+
var longestCommonSubsequence = function (text1, text2) {
21+
const memo = new Map();
22+
23+
const dfs = (i, j) => {
24+
const key = `${i},${j}`; // Convert (i, j) into a unique string key
25+
if (memo.has(key)) {
26+
return memo.get(key);
27+
}
28+
29+
if (i === text1.length || j === text2.length) {
30+
memo.set(key, 0);
31+
} else if (text1[i] === text2[j]) {
32+
memo.set(key, 1 + dfs(i + 1, j + 1));
33+
} else {
34+
memo.set(key, Math.max(dfs(i + 1, j), dfs(i, j + 1)));
35+
}
36+
37+
return memo.get(key);
38+
};
39+
return dfs(0, 0);
40+
};
41+
42+
// 😊 bottom-up dynamic programming approach
43+
// Time Complexity: O(m * n), where m is the length of text1, and n is the length of text2
44+
// Space Complexity: O(m * n)
45+
46+
// text1 = "abcde"
47+
// text2 = "ace"
48+
49+
// "" a c e
50+
// "" 0 0 0 0
51+
// a 0 1 1 1
52+
// b 0 1 1 1
53+
// c 0 1 2 2
54+
// d 0 1 2 2
55+
// e 0 1 2 3
56+
57+
58+
// var longestCommonSubsequence = function (text1, text2) {
59+
// const dp = new Array(text1.length + 1)
60+
// .fill(0)
61+
// .map(() => new Array(text2.length + 1).fill(0));
62+
63+
// for (let i = 1; i <= text1.length; i++) {
64+
// for (let j = 1; j <= text2.length; j++) {
65+
// if (text1[i - 1] === text2[j - 1]) {
66+
// dp[i][j] = dp[i - 1][j - 1] + 1;
67+
// } else {
68+
// dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
69+
// }
70+
// }
71+
// }
72+
73+
// return dp[text1.length][text2.length];
74+
// };
75+
76+
77+
// 😱 Time Limit Exceeded!
78+
// Brute-force Recursion
79+
// Time Complexity: O(2^(m+n)) (Exponential)
80+
// Space Complexity: O(m + n) (Recursive Stack)
81+
82+
// var longestCommonSubsequence = function (text1, text2) {
83+
// const dfs = (i, j) => {
84+
// if (i === text1.length || j === text2.length) {
85+
// return 0;
86+
// }
87+
// if (text1[i] === text2[j]) {
88+
// return 1 + dfs(i + 1, j + 1);
89+
// }
90+
// return Math.max(dfs(i + 1, j), dfs(i, j + 1));
91+
// };
92+
// return dfs(0, 0);
93+
// };
94+
95+

0 commit comments

Comments
 (0)