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

update Chapter1 IsUnique with O(n) algorithm #45

Open
wants to merge 2 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
54 changes: 52 additions & 2 deletions chapter01/1.1 - Is Unique/isUnique.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

var allUniqueChars = function(string) {

// O(n^2) approach, no additional data structures used
// for each character, check remaining characters for duplicates
for (var i = 0; i < string.length; i++) {
Expand All @@ -12,5 +14,53 @@ var allUniqueChars = function(string) {
return true; // if no match, return true
};



var allUniqueChars2 = function(string) {
// O(n) approach and Space complexity O(1)
// Assume to use ASCII character set (7 bit, 128 positions)
// If we assume to use exended ASCII (8 bit), then check 256 positions.

// If the string length exceeds the number of unique characters in the alphabet, return false
if (string.length > 128) return false;
const charactersArray = new Array(128);
for (let i = 0; i < string.length; i++) {
const val = string.charCodeAt(i);
if (charactersArray[val]) {
return false;
}
charactersArray[val] = true;
}
return true;
}


/* TESTS */
// log some tests here
console.log(allUniqueChars('abcd'), true);
console.log(allUniqueChars('abab'), false);
console.log(allUniqueChars2('abcd'), true);
console.log(allUniqueChars2('abab'), false);


/* TESTS - Performance check */

var buildReadableASCII = function(){
//Creates a string with readable ASCII characters (from position 32, and to make the code more readable we leave also the last one, 'DEL')

let temp = '';
for (var i = 32; i < 128; ++i) {
temp += String.fromCharCode(i);
}
return temp;
}

const testString = buildReadableASCII();
console.log('Readable ASCII' + testString);

console.time('basic');
console.log(allUniqueChars(testString), true);
console.timeEnd('basic');

console.time('new');
console.log(allUniqueChars2(testString), true);
console.timeEnd('new');
12 changes: 9 additions & 3 deletions chapter01/1.2 - Check Perm/checkPermute.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
/**
* Check Permutation
* Given two strings, write a method to decide if one is a
* permutation of the other. We should understand if the permutation comparison
*is case sensitive. Additionally, we should ask if whitespace is significant
**/
var checkPermute = function(stringOne, stringTwo) {
// if different lengths, return false
if (stringOne.length !== stringTwo.length) {
return false;
// else sort and compare
// (doesnt matter how it's sorted, as long as it's sorted the same way)
// else sort and compare
// (doesnt matter how it's sorted, as long as it's sorted the same way)
} else {
var sortedStringOne = stringOne.split('').sort().join('');
var sortedStringTwo = stringTwo.split('').sort().join('');
Expand All @@ -16,4 +22,4 @@ console.log(checkPermute('aba', 'aab'), true);

console.log(checkPermute('aba', 'aaba'), false);

console.log(checkPermute('aba', 'aa'), false);
console.log(checkPermute('aba', 'aa'), false);
61 changes: 58 additions & 3 deletions chapter01/1.4 - PalinPerm/palinPerm.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ var palinPerm = function(string) {
// check that all chars are even count, except for one exception
Object.keys(chars).forEach((char) => {
if (chars[char] % 2 > 0) {
// if more than one exception, return false
// if more than one exception, return false
if (mulligan) {
isPerm = false; // return in a forEach statment doesn't flow out of function scope
isPerm = false; // return in a forEach statment doesn't flow out of
// function scope
} else {
mulligan = true;
}
Expand All @@ -31,4 +32,58 @@ var palinPerm = function(string) {

// TESTS
console.log(palinPerm('Tact Coa'), 'true');
console.log(palinPerm('Tact boa'), 'false');
console.log(palinPerm('Tact boa'), 'false');



/**
* If you find more than one character odd, the string is not palindrome
* This algorithm takes O ( N) time, where N is the length of the string.
*/
var palinPerm2 = function(string) {
var table = buildTable(string);
return checkOneOdd(table);

function checkOneOdd(table) {
isOneOdd = false;

for (var i of table) {
if (i % 2 == 1) {
if (isOneOdd) return false;
isOneOdd = true
}
}
return true;
}

function getCharacterCode(item) {
var a = (new String('a')).charCodeAt(0);
var z = (new String('z')).charCodeAt(0);
var currentValue = (new String(item)).charCodeAt(0);

if ((a <= currentValue) && (currentValue <= z)) {
return currentValue - a;
}
return -1;
}

function buildTable(string) {
var arr = [];
for (var i = 0; i < string.length; i++) {
var position = getCharacterCode(string[i]);
if (position !== -1) {
if (arr[position] === undefined) {
arr[position] = 1
} else {
arr[position] += 1;
}
}
}
return arr;
}
};

console.log('----');
console.log(palinPerm2('abc'), false);
console.log(palinPerm2('abcab'), true);
console.log(palinPerm2('abcdabc'), true);
86 changes: 72 additions & 14 deletions chapter01/1.5 - OneAway/oneAway.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ var oneAway = function(string1, string2) {
return false;
} else {
var mulligan = false;
var fP = 0; // first Pointer
var sP = 0; // second Pointer
var fP = 0; // first Pointer
var sP = 0; // second Pointer
while (fP < first.length) {
if (first[fP] !== second[sP]) {
if (mulligan) {
return false;
} else {
mulligan = true;
sP++; // second length is longer
sP++; // second length is longer
}
} else {
fP++;
Expand All @@ -29,14 +29,14 @@ var oneAway = function(string1, string2) {
return false;
} else {
var mulligan = false;
var fP = 0; // first Pointer
var sP = 0; // second Pointer
var fP = 0; // first Pointer
var sP = 0; // second Pointer
while (fP < first.length) {
if (first[fP] !== second[sP]) {
if (mulligan) {
return false; // more than one mismatch
return false; // more than one mismatch
} else {
mulligan = true; // use up mulligan
mulligan = true; // use up mulligan
}
}
fP++;
Expand All @@ -48,17 +48,75 @@ var oneAway = function(string1, string2) {
// insert a char for str1 -> remove a char for str2
// check one diff

// console log checks
// console.log(string1, string2, 'checkMiss', checkOneMissing(string1, string2));
// console.log(string2, string1, 'checkMiss', checkOneMissing(string2, string1));
// console.log(string1, string2, 'checkDiff', checkOneDiff(string1, string2));

return checkOneMissing(string1, string2) || checkOneMissing(string2, string1) || checkOneDiff(string1, string2);
return checkOneMissing(string1, string2) ||
checkOneMissing(string2, string1) || checkOneDiff(string1, string2);
};


// Test
console.log(oneAway('pale', 'ple'), true);
console.log(oneAway('pales', 'pale'), true);
console.log(oneAway('pale', 'bale'), true);
console.log(oneAway('pale', 'bake'), false);
console.log(oneAway('pale', 'bake'), false);



console.log('----------------');

// There are three types of edits that can be performed on strings: insert a
// character, remove a character, or replace a character. Given two strings,
// write a function to check if they are one edit (or zero edits) away. EXAMPLE
// pale, ple -> true
// pales, pale -> true
// pale, bale -> true
// pale, bae -> false

// This algorithm (and almost any reasonable algorithm) takes O ( n) time, where
// n is the length of the shorter string.

function oneEditWay(string1, string2) {
if (string1.length === string2.length) {
return oneEditReplace(string1, string2);
} else if (string1.length + 1 === string2.length) {
return oneEditInsert(string1, string2);
} else if (string1.length == string2.length + 1) {
return oneEditInsert(string2, string1);
}
}

function oneEditReplace(string1, string2) {
foundDifference = false;

for (let i = 0; i < string1.length; i++) {
if (string1[i] !== string2[i]) {
if (foundDifference) return false;
foundDifference = true;
}
}
return foundDifference;
}

/* Check if you can insert a character into sl to make s2. */
function oneEditInsert(string1, string2) {
var indexS1, indexS2 = 0;

while (indexS1 < string1.length && indexS2 < string2.length) {
if (string1[indexS1] !== string2[indexS2]) {
if (indexS1 != indexS2) {
return false;
}
indexS2++
} else {
indexS1++;
indexS2++;
}
}
return true;
}


// Test
console.log(oneEditWay('pale', 'ple'), true);
console.log(oneEditWay('pales', 'pale'), true);
console.log(oneEditWay('pale', 'bale'), true);
console.log(oneEditWay('pale', 'bake'), false);
46 changes: 44 additions & 2 deletions chapter01/1.6 - String Compression/strComp.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var strComp = function(string) {
var maxCount = 1;
for (var i = 0; i < string.length; i++) {
if (currChar !== string[i]) {
console.log(currChar, string[i], i);
// console.log(currChar, string[i], i);
compressed = compressed + currChar + currCount;
maxCount = Math.max(maxCount, currCount);
currChar = string[i];
Expand All @@ -22,4 +22,46 @@ var strComp = function(string) {

// Test
console.log('aaaaaa', strComp('aaaaaa'), 'a6');
console.log('aabcccccaaa', strComp('aabcccccaaa'), 'a2b1c5a3');
console.log('aabcccccaaa', strComp('aabcccccaaa'), 'a2b1c5a3');

// variant

function compress(inputString) {
if (inputString.length <= checkCompressionLength(inputString))
return inputString;

function doCompression(inputString) {
countConsecutive = 0;
compressString = '';
for (var i = 0; i < inputString.length; i++) {
countConsecutive++;
if (inputString[i] !== inputString[i + 1]) {
compressString += inputString[i];
compressString += countConsecutive;
countConsecutive = 0;
}
}
return compressString;
}


function checkCompressionLength(inputString) {
countCompressedLength = 0;
countConsecutive = 0;

for (var i = 0; i < inputString.length; i++) {
countConsecutive++;
if (inputString[i] !== inputString[i + 1]) {
countConsecutive = 0;
countCompressedLength += (1 + countConsecutive.toString().length);
}
}
return countCompressedLength;
}
return doCompression(inputString);
}


console.log('aaaaaa', compress('aaaaaa'), 'a6');
console.log('abc', compress('abc'), 'abc');
console.log('aabcccccaaa', compress('aabcccccaaa'), 'a2b1c5a3');
Loading