Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add one more solution 'isPalindromePermutationsBit' to ch1-q4, fix issue #3 . #18

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions src/chapter1/ch1-q4.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,50 @@ export function isPalindromePermutationsSet(str) {
let chars = new Set();
for (let char of str) {
if (char !== ' ') { // ignore spaces
if (chars.has(char)) {
chars.delete(char);
let lchar = char.toLowerCase();
if (chars.has(lchar)) {
chars.delete(lchar);
}
else {
chars.add(char);
chars.add(lchar);
}
}
}

return chars.size <= 1;
}

/**
* Use a Number in binray form as a series of flags. Convert each coming
* letter (English Alphabet) to lowercase and map it to an integer between 0 and 26,
* see it as the position of bit and toggle this bit. After iteration, check if
* flags has at most one bit that is set to 1.
*
* N = |str|
* Time: O(N)
* Additional space: O(1)
*
* @param {string[]} str String to check as a character array
* @return {boolean} True if input string is a permutation of a palindrome (ignoring spaces), otherwise false
*/

export function isPalindromePermutationsBit(str) {
if (!str) {
return false;
}

let flags = 0;

for (let char of str) {
if (char !== ' ') {
flags ^= (1 << (char.toLowerCase().charCodeAt(0) - 'a'.charCodeAt(0)));
}
}

return (((flags - 1) & flags) === 0); // Abuse only 4 bits for brief explanation here.
// flags: 0110, 0110 - 0001 = 0101, 0101 & 0110 = 0100
// flags: 0100, 0100 - 0001 = 0011, 0011 & 0100 = 0000
// flags: 0000, 0 - 1 = -1, 1111 (two's complement) & 0000 = 0000
}


38 changes: 31 additions & 7 deletions src/chapter1/ch1-q4.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,53 @@ for (let key in funcs) {
[
' ',
' ',
'Tact Coa',
'aabb',
'ab a b',
' a b a b ',
'sasadfgsadfghjk;hjk;sadfghjk;dfghjk;',
'sa sadfgsadfgh jk;hjkz;sadfg hjk;dfghjk;'
].forEach(arg => {

it(`returns true for palindromic string: '${arg}'`, function() {
expect(func(arg.split(''))).to.be.true;
});
if (key === 'isPalindromePermutationsBit') {
if(/^[a-zA-Z\s]+$/.test(arg)) {

it(`returns true for palindromic string which only contains English alphabet and space: '${arg}'`, function() {
expect(func(arg.split(''))).to.be.true;
});

}
} else {

it(`returns true for palindromic string: '${arg}'`, function() {
expect(func(arg.split(''))).to.be.true;
});

}
});

[
'abcadef',
'1234567890',
'a b'
'a b',
'sg! sG$'
].forEach(arg => {

it(`returns false for non-palindromic string: '${arg}'`, function() {
expect(func(arg.split(''))).to.be.false;
});
if (key === 'isPalindromePermutationsBit') {
if(/^[a-zA-Z\s]+$/.test(arg)) {

it(`returns false for palindromic string which only contains English alphabet and space: '${arg}'`, function() {
expect(func(arg.split(''))).to.be.false;
});

}
} else {

it(`returns false for non-palindromic string: '${arg}'`, function() {
expect(func(arg.split(''))).to.be.false;
});

}
});

});
Expand Down