Skip to content

Commit f2c7155

Browse files
committed
Added 2 JS solutions for problem 567
1 parent 0868645 commit f2c7155

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
//////////////////////////////////////////////////////////////////////////////
2+
// Static Sliding Window
3+
// Time: Theta(l1 + l2) O(l1 + l2) Space: Theta(1) O(1)
4+
// Highest performing solution. Simply builds a map of the character counts
5+
// for `s1` and `s1.length` of `s2`, updates the `s2` character map as it
6+
// slides from the beginning of `s2` to the end of `s2`, and returns upon
7+
// verifying a match between the `s1` and `s2` character maps.
8+
//////////////////////////////////////////////////////////////////////////////
9+
10+
const CHARS = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
11+
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ];
12+
13+
/**
14+
* @param {string} s1
15+
* @param {string} s2
16+
* @return {boolean}
17+
*/
18+
function checkInclusion(s1, s2) {
19+
20+
if (s1.length > s2.length) {
21+
return false;
22+
}
23+
24+
const s1Chars = buildCharsMap(s1);
25+
const s2Chars = buildCharsMap(s2, s1.length);
26+
27+
let matches = 0;
28+
29+
for (const ch of CHARS) {
30+
if (s1Chars[ch] === s2Chars[ch]) {
31+
++matches;
32+
}
33+
}
34+
35+
const last = s2.length - s1.length;
36+
37+
for (let i = 0; i <= last; ++i) {
38+
39+
if (matches === CHARS.length) {
40+
return true;
41+
}
42+
43+
const ch1 = s2[i];
44+
const ch2 = s2[i + s1.length];
45+
46+
if (s1Chars[ch1] === s2Chars[ch1]--) {
47+
--matches;
48+
} else if (s1Chars[ch1] === s2Chars[ch1]) {
49+
++matches;
50+
}
51+
52+
if (s1Chars[ch2] === s2Chars[ch2]++) {
53+
--matches;
54+
} else if (s1Chars[ch2] === s2Chars[ch2]) {
55+
++matches;
56+
}
57+
}
58+
59+
return matches === CHARS.length;
60+
}
61+
62+
/**
63+
* @param {string} s
64+
* @param {number=} length = `s.length`
65+
* @return {boolean}
66+
*/
67+
function buildCharsMap(s, length = s.length) {
68+
69+
const chars = Object.create(null);
70+
71+
for (const ch of CHARS) {
72+
chars[ch] = 0;
73+
}
74+
75+
for (let i = 0; i < length; ++i) {
76+
++chars[s[i]];
77+
}
78+
79+
return chars;
80+
}
81+
82+
//////////////////////////////////////////////////////////////////////////////
83+
// Optimized Backtracking
84+
// Time: Theta(l1 + l2) O(l1 + l2^2) Space: Theta(l1) O(l1)
85+
// This solution passes the tests, but it is much slower than other passing
86+
// solutions. At each possible beginning character of `s1` within `s2` a fresh
87+
// map is created and a second pointer increments until it either matches `s1`
88+
// or fails and moves the first and second pointer to the next available
89+
// matching index.
90+
//////////////////////////////////////////////////////////////////////////////
91+
92+
/**
93+
* @param {string} s1
94+
* @param {string} s2
95+
* @return {boolean}
96+
*/
97+
function checkInclusion(s1, s2) {
98+
99+
if (s1.length > s2.length) {
100+
return false;
101+
}
102+
103+
const s1Chars = Object.create(null);
104+
105+
for (const ch of s1) {
106+
if (!(ch in s1Chars)) {
107+
s1Chars[ch] = 0;
108+
}
109+
++s1Chars[ch];
110+
}
111+
112+
const last = s2.length - s1.length;
113+
let i = 0;
114+
115+
while (i <= last) {
116+
117+
while (i <= last && !(s2[i] in s1Chars)) {
118+
++i;
119+
}
120+
121+
if (i > last) {
122+
return false;
123+
}
124+
125+
const subChars = Object.create(null);
126+
let j = i;
127+
128+
while (j < s2.length && s2[j] in s1Chars) {
129+
130+
const ch = s2[j];
131+
132+
if (!(ch in subChars)) {
133+
subChars[ch] = 0;
134+
}
135+
++subChars[ch];
136+
137+
if (subChars[ch] > s1Chars[ch]) {
138+
break;
139+
}
140+
141+
++j;
142+
}
143+
144+
if (s1.length === j - i) {
145+
return true;
146+
}
147+
148+
if (j < s2.length && s2[j] in s1Chars) {
149+
while (s2[i] !== s2[j]) {
150+
++i;
151+
}
152+
++i;
153+
} else {
154+
i = j;
155+
}
156+
}
157+
158+
return false;
159+
}

0 commit comments

Comments
 (0)