Skip to content

Commit 303c12f

Browse files
committed
refactor: js | 2dp
1 parent 18ee23d commit 303c12f

11 files changed

+1307
-342
lines changed
+86-26
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,98 @@
11
/**
2+
* Brute Force - DFS
3+
* Time O((N + M) * 2^(N + (M / 2))) | Space O(N^2 + M^2)
4+
* https://leetcode.com/problems/regular-expression-matching/
25
* @param {string} s
36
* @param {string} p
47
* @return {boolean}
58
*/
6-
var isMatch = function (s, p) {
7-
var lenS = s.length;
8-
var lenP = p.length;
9-
var map = {};
9+
var isMatch = (text, pattern) => {
10+
const isBaseCase = (pattern.length === 0);
11+
if (isBaseCase) return (text.length === 0);
1012

11-
return check(0, 0);
13+
const isTextAndPatternEqual = (pattern[0] === text[0]),
14+
isPatternPeriod = (pattern[0] === '.'),
15+
isFirstMatch = (text && (isTextAndPatternEqual || isPatternPeriod)),
16+
isNextPatternWildCard = (pattern.length >= 2 && pattern[1] === '*');
1217

13-
function check(idxS, idxP) {
14-
if (map[idxS + ':' + idxP] !== undefined) {
15-
return map[idxS + ':' + idxP];
16-
}
18+
return isNextPatternWildCard/* Time O((N + M) * 2^(N + (M / 2))) | Space O(N^2 + M^2) */
19+
? (isMatch(text, pattern.slice(2)) || (isFirstMatch && isMatch(text.slice(1), pattern)))
20+
: (isFirstMatch && isMatch(text.slice(1), pattern.slice(1)));
21+
};
1722

18-
if (idxS > lenS) {
19-
return false;
20-
}
23+
/**
24+
* DP - Top Down
25+
* Matrix - Memoization
26+
* Time O(N * M) | Space O(N * M)
27+
* https://leetcode.com/problems/regular-expression-matching/
28+
* @param {string} s
29+
* @param {string} p
30+
* @return {boolean}
31+
*/
32+
var isMatch = (text, pattern, row = 0, col = 0, memo = initMemo(text, pattern)) => {
33+
const hasSeen = (memo[row][col]);
34+
if (hasSeen) return memo[row][col];
2135

22-
if (idxS === lenS && idxP === lenP) {
23-
return true;
24-
}
36+
const isEqual = (col === pattern.length);
37+
const ans = isEqual
38+
? row === text.length
39+
: check(text, pattern, row, col, memo);/* Time O(N * M) | Space O(N * M) */
2540

26-
if (p[idxP] === '.' || p[idxP] === s[idxS]) {
27-
map[idxS + ':' + idxP] =
28-
p[idxP + 1] === '*'
29-
? check(idxS + 1, idxP) || check(idxS, idxP + 2)
30-
: check(idxS + 1, idxP + 1);
31-
} else {
32-
map[idxS + ':' + idxP] =
33-
p[idxP + 1] === '*' ? check(idxS, idxP + 2) : false;
34-
}
41+
memo[row][col] = ans;
42+
return ans;
43+
}
44+
45+
var initMemo = (text, pattern) => new Array((text.length + 1)).fill()/* Time O(N) | Space O(N) */
46+
.map(() => new Array((pattern.length + 1)).fill(false)) /* Time O(M) | Space O(M) */
47+
48+
var check = (text, pattern, row, col, memo) => {
49+
const isTextDefined = (row < text.length),
50+
isTextAndPatternEqual = (pattern[col] === text[row]),
51+
isPatternPeriod = (pattern[col] === '.'),
52+
isFirstMatch = (isTextDefined && (isTextAndPatternEqual || isPatternPeriod)),
53+
isNextPatternWildCard = (((col + 1) < pattern.length) && pattern[col + 1] === '*');
54+
55+
return isNextPatternWildCard/* Time O(N * M) | Space O(N * M) */
56+
? (isMatch(text, pattern, row, (col + 2), memo) || isFirstMatch && isMatch(text, pattern, (row + 1), col, memo))
57+
: (isFirstMatch && isMatch(text, pattern, (row + 1), (col + 1), memo));
58+
}
59+
60+
/**
61+
* Time O(N * M) | Space O(N * M)
62+
* @param {string} s
63+
* @param {string} p
64+
* @return {boolean}
65+
*/
66+
var isMatch = (text, pattern) => {
67+
const tabu = initTabu(text, pattern);/* Time O(N * M) | Space O(N * M) */
68+
69+
search(text, pattern, tabu); /* Time O(N * M) | Space O(N * M) */
70+
71+
return tabu[0][0];
3572

36-
return map[idxS + ':' + idxP];
73+
}
74+
75+
var initTabu = (text, pattern) => {
76+
const tabu = new Array((text.length + 1)).fill() /* Time O(N) | Space O(N) */
77+
.map(() => new Array((pattern.length + 1)).fill(false));/* Time O(M) | Space O(M) */
78+
79+
tabu[text.length][pattern.length] = true; /* | Space O(N * M) */
80+
81+
return tabu
82+
}
83+
84+
var search = (text, pattern, tabu) => {
85+
for (let row = text.length; 0 <= row; row--){ /* Time O(N) */
86+
for (let col = (pattern.length - 1); (0 <= col); col--){/* Time O(M) */
87+
const isTextDefined = row < text.length,
88+
isTextAndPatternEqual = pattern[col] === text[row],
89+
isPatternPeriod = pattern[col] === '.',
90+
isFirstMatch = isTextDefined && (isTextAndPatternEqual || isPatternPeriod),
91+
isNextPatternWildCard = col + 1 < pattern.length && pattern[col + 1] === '*';
92+
93+
tabu[row][col] = isNextPatternWildCard /* Space O(N * M) */
94+
? tabu[row][col + 2] || (isFirstMatch && tabu[row + 1][col])
95+
: isFirstMatch && tabu[row + 1][col + 1];
96+
}
3797
}
38-
};
98+
}
+141-13
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,144 @@
1-
var longestCommonSubsequence = function (text1, text2) {
2-
let m = text1.length,
3-
n = text2.length,
4-
DP = new Array(m + 1).fill(0).map((_) => new Array(n + 1).fill(0));
5-
6-
for (let x = m - 1; x >= 0; x--)
7-
for (let y = n - 1; y >= 0; y--) {
8-
if (text1[x] === text2[y]) {
9-
DP[x][y] = 1 + DP[x + 1][y + 1];
10-
} else {
11-
DP[x][y] = Math.max(DP[x + 1][y], DP[x][y + 1]);
12-
}
1+
/**
2+
* DP - Top Down
3+
* Matrix - Memoization
4+
* Time O(N * (M^2)) | Space O(N * M)
5+
* https://leetcode.com/problems/longest-common-subsequence/
6+
* @param {string} text1
7+
* @param {string} text2
8+
* @return {number}
9+
*/
10+
var longestCommonSubsequence = (text1, text2, p1 = 0, p2 = 0, memo = initMemo(text1, text2)) => {
11+
const isBaseCase = ((p1 === text1.length) || (p2 === text2.length));
12+
if (isBaseCase) return 0;
13+
14+
const hasSeen = (memo[p1][p2] !== null);
15+
if (hasSeen) return memo[p1][p2];
16+
17+
return dfs(text1, text2, p1, p2, memo);/* Time O((N * M) * M)) | Space O((N * M) + HEIGHT) */
18+
}
19+
20+
var initMemo = (text1, text2) => new Array((text1.length + 1)).fill()/* Time O(N) | Space O(N) */
21+
.map(() => new Array((text2.length + 1)).fill(null)); /* Time O(M) | Space O(M) */
22+
23+
var dfs = (text1, text2, p1, p2, memo) => {
24+
const left = longestCommonSubsequence(text1, text2, (p1 + 1), p2, memo); /* Time O(N * M) | Space O(HEIGHT) */
25+
26+
const index = text2.indexOf(text1[p1], p2); /* Time O(M) */
27+
const isPrefix = (index !== -1);
28+
29+
const right = isPrefix
30+
? (longestCommonSubsequence(text1, text2, (p1 + 1), (index + 1), memo) + 1)/* Time O(N * M) | Space O(HEIGHT) */
31+
: 0;
32+
33+
memo[p1][p2] = Math.max(left, right); /* | Space O(N * M) */
34+
return memo[p1][p2];
35+
}
36+
37+
/**
38+
* DP - Top Down
39+
* Matrix - Memoization
40+
* Time O(N * M) | Space O(N * M)
41+
* https://leetcode.com/problems/longest-common-subsequence/
42+
* @param {string} text1
43+
* @param {string} text2
44+
* @return {number}
45+
*/
46+
var longestCommonSubsequence = (text1, text2, p1 = 0, p2 = 0, memo = initMemo(text1, text2)) => {
47+
const isBaseCase = ((p1 === text1.length) || (p2 === text2.length));
48+
if (isBaseCase) return 0;
49+
50+
const hasSeen = (memo[p1][p2] !== null);
51+
if (hasSeen) return memo[p1][p2];
52+
53+
return dfs(text1, text2, p1, p2, memo);/* Time O(N * M) | Space O((N * M) + HEIGHT) */
54+
}
55+
56+
var initMemo = (text1, text2) => new Array((text1.length + 1)).fill()/* Time O(N) | Space O(N) */
57+
.map(() => new Array((text2.length + 1)).fill(null)); /* Time O(M) | Space O(M) */
58+
59+
var dfs = (text1, text2, p1, p2, memo) => {
60+
const left = (longestCommonSubsequence(text1, text2, (p1 + 1), (p2 + 1), memo) + 1);/* Time O(N * M) | Space O(HEIGHT) */
61+
const right = /* Time O(N * M) | Space O(HEIGHT) */
62+
Math.max(longestCommonSubsequence(text1, text2, p1, (p2 + 1), memo), longestCommonSubsequence(text1, text2, (p1 + 1), p2, memo));
63+
64+
const isEqual = (text1[p1] == text2[p2]);
65+
const count = isEqual
66+
? left
67+
: right
68+
69+
memo[p1][p2] = count; /* | Space O(N * M) */
70+
return memo[p1][p2];
71+
}
72+
73+
/**
74+
* DP - Bottom Up
75+
* Matrix - Tabulation
76+
* Time O(N * M) | Space O(N * M)
77+
* https://leetcode.com/problems/longest-common-subsequence/
78+
* @param {string} text1
79+
* @param {string} text2
80+
* @return {number}
81+
*/
82+
var longestCommonSubsequence = (text1, text2) => {
83+
const tabu = initTabu(text1, text2);/* Time O(N * M) | Space O(N * M) */
84+
85+
search(text1, text2, tabu); /* Time O(N * M) | Space O(N * M) */
86+
87+
return tabu[0][0];
88+
};
89+
90+
var initTabu = (text1, text2) =>
91+
new Array((text1.length + 1)).fill() /* Time O(N) | Space O(N) */
92+
.map(() => new Array((text2.length + 1)).fill(0));/* Time O(M) | Space O(M) */
93+
94+
var search = (text1, text2, tabu) => {
95+
const [ n, m ] = [ text1.length, text2.length ];
96+
97+
for (let x = (n - 1); (0 <= x); x--) {/* Time O(N) */
98+
for (let y = (m - 1); (0 <= y); y--) {/* Time O(M) */
99+
tabu[x][y] = (text1[x] === text2[y]) /* Space O(N * M) */
100+
? (tabu[x + 1][y + 1] + 1)
101+
: Math.max(tabu[x + 1][y], tabu[x][y + 1]);
13102
}
103+
}
104+
}
105+
106+
/**
107+
* DP - Bottom Up
108+
* Matrix - Tabulation
109+
* Time O(N * M) | Space O(M)
110+
* https://leetcode.com/problems/longest-common-subsequence/
111+
* @param {string} text1
112+
* @param {string} text2
113+
* @return {number}
114+
*/
115+
var longestCommonSubsequence = (text1, text2) => {
116+
const canSwap = (text2.length < text1.length);
117+
if (canSwap) [ text1, text2 ] = [ text2, text1 ];
118+
119+
let tabu = initTabu(text1); /* Time O(M) | Space O(M) */
120+
121+
tabu = search(text1, text2, tabu);/* Time O(N * M) | Space O(M) */
14122

15-
return DP[0][0];
123+
return tabu[0];
16124
};
125+
126+
var initTabu = (text1) => new Array((text1.length + 1)).fill(0)
127+
128+
var search = (text1, text2, tabu) => {
129+
for (let col = (text2.length - 1); (0 <= col); col--) {/* Time O(N) */
130+
const temp = initTabu(text1); /* Space O(M) */
131+
132+
for (let row = (text1.length - 1); (0 <= row); row--) {/* Time O(M) */
133+
const isEqual = (text1[row] == text2[col]);
134+
135+
temp[row] = isEqual /* Space O(M) */
136+
? (tabu[(row + 1)] + 1)
137+
: Math.max(tabu[row], temp[(row + 1)]);
138+
}
139+
140+
tabu = temp; /* Space O(M) */
141+
}
142+
143+
return tabu;
144+
}

0 commit comments

Comments
 (0)