Skip to content

Commit 35b3314

Browse files
authored
avc278 - 1.02 - Javascript (#54)
Added my solution to the Chapter 1 Problem 2 folder.
1 parent 1639622 commit 35b3314

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Check Permutation: Given two strings, write a method to decide if one is a permutation of the other.
2+
3+
const assert = require("assert");
4+
const { DH_CHECK_P_NOT_PRIME } = require("constants");
5+
6+
/**
7+
* Checks if a string is a permutation of another
8+
* @param {string} A source input string to check against
9+
* @param {string} B target input string to compare with source string
10+
* @return {bool} Whether the input strings are permutations of one another
11+
*
12+
* Throughout the problem, we set up a couple ways to early exit. At the start, if both strings are not of the same
13+
* length, we already know they cannot be permutations of each other, so we return false.
14+
* Otherwise, we can continue and set up a mapping between the elements in A and B, and their frequencies.
15+
* This is an O(N) operation with respect to time and space where N is the length of the string A.
16+
* At this point, we can get the keys from the frequency objects we created, which is an O(N) operation for space.
17+
* If the lengths of `aKeys` and `bKeys` are not the same, we know they cannot be permutations and we exit early.
18+
* Otherwise, we can continue to iterate through the keys. We need to make sure that the frequencies of aKeys exist in
19+
* both aFreq and bFreq. If at any point, they do not match, we can return false.
20+
*
21+
* If we haven't returned false up to this point, it's safe to return true.
22+
*
23+
* Runtime: O(N)
24+
* Space: O(N)
25+
*
26+
*/
27+
const checkPermutation1 = (A, B) => {
28+
if (A.length !== B.length) return false;
29+
const aFreq = {};
30+
const bFreq = {};
31+
for (const a of A) {
32+
aFreq[a] = (aFreq[a] || 0) + 1;
33+
}
34+
for (const b of B) {
35+
bFreq[b] = (bFreq[b] || 0) + 1;
36+
}
37+
38+
const aKeys = Object.keys(aFreq);
39+
const bKeys = Object.keys(bFreq);
40+
if (aKeys.length !== bKeys.length) return false;
41+
for (let i = 0; i < aKeys.length; i++) {
42+
if (aFreq[aKeys[i]] !== bFreq[aKeys[i]]) return false;
43+
}
44+
45+
return true;
46+
};
47+
48+
/**
49+
* Checks if a string is a permutation of another
50+
* @param {string} A source input string to check against
51+
* @param {string} B target input string to compare with source string
52+
* @return {bool} Whether the input strings are permutations of one another
53+
*
54+
* An alternative to this problem, and significantly more elegant, is to simply split the input strings into arrays,
55+
* use the built-in sort array method, then join back to a string, and check if A and B are equal.
56+
* The trade off is since we sort arrays of length N, the runtime becomes slower from O(N) to O(NlogN).
57+
* As for space, we create arrays of length N, so there is no change to space performance compared to checkPermutation1.
58+
* Even though this is less performant to checkPermutation1, for production code, this seems to be more maintainable
59+
* and way easier to read at a glance.
60+
*
61+
* Runtime: O(NlogN)
62+
* Space: O(N)
63+
*
64+
*/
65+
const checkPermutation2 = (A, B) => {
66+
if (A.length !== B.length) return false;
67+
68+
A = A.split("").sort().join("");
69+
B = B.split("").sort().join("");
70+
71+
return A === B;
72+
};
73+
74+
const checkPermutations = [checkPermutation1, checkPermutation2];
75+
checkPermutations.forEach((checkPerm) => {
76+
describe(checkPerm.name, () => {
77+
it("should return false on input strings not of the same size", () => {
78+
const A = "hello";
79+
const B = "hi";
80+
assert.ok(!checkPerm(A, B));
81+
});
82+
it("should return false on input strings whose key lengths do not match", () => {
83+
const A = "abcd";
84+
const B = "abcc";
85+
assert.ok(!checkPerm(A, B));
86+
});
87+
it("should return false on input strings whose key frequencies do not match", () => {
88+
const A = "abccd";
89+
const B = "abcce";
90+
assert.ok(!checkPerm(A, B));
91+
});
92+
it("should return true on input strings whose letter frequencies match", () => {
93+
const A = "racecar";
94+
const B = "aaccerr";
95+
assert.ok(checkPerm(A, B));
96+
});
97+
})
98+
})

0 commit comments

Comments
 (0)