Calculate how many sub-strings of a string are palindromes - javascript

I'm currently trying to work out how many substrings of a given string are palindromes.
When given the string aabaa the expected output is 5 however my code outputs 4. I'm not too sure why, can any one help me solve this?
My code:
function countPalindromesInString(s) {
let count = 0;
if (s === s.split('').reverse().join('')) {
count += 1;
}
let testStr = '';
for (let i = 0; i < s.length; i++) {
testStr += s[i];
if (testStr === testStr.split('').reverse().join('')) {
count += 1;
}
}
return count;
}

I'm not sure why you expect output 5 for input aabaa.
From my point of view, if you consider a single letter as a palindrome than the output should be 9, otherwise the result should be 4: "aa", "aa", "aba", "aabaa". Your code only count from left to right and also double counts the full 5 letter string, once in the beginning, here:
if (s === s.split('').reverse().join('')) {
count += 1;
}
and once in the for loop for case i=4;
Here is a solution to your question:
function countPalindromesInString(s) {
let count = 0; //or s.length if you chose to count single letters as palindrome
let subString;
for (let i = 1; i < s.length; i++) {
for(let j = 0; j < s.length - i; j++) {
subString = s.substring(j, j+i+1);
if(subString === subString.split('').reverse().join('')) {
count += 1;
}
}
}
return count;
}
Later Edit:
If we want to count unique palindromes in your string, we can store the palindromes found in an array and every time we find another one, we check if it was previously added:
function countPalindromesInString(s) {
let subStrings = [];
for (let i = 0; i < s.length; i++) {
for(let j = 0; j < s.length - i; j++) {
let subString = s.substring(j, j+i+1);
if(subString === subString.split('').reverse().join('') && !subStrings.includes(subString)) {
subStrings.push(subString);
}
}
}
return subStrings.length;
}

Related

JavaScript Compression String

Defined a function that takes one argument (a string) and returns another string.
Input example: aabcc
Output example: a2bc2
function compressedString(message) {
if (message.length == 0) {
return;
}
var result = "";
var count = 0;
for (var n = 0; n < message.length; n++) {
count++;
if (message[n] != message[n+1]) {
result += message[n] + count;
count = 0;
}
}
return result;
}
console.log(compressedString('aabcc'));
Output I am getting: a1b1c1
Looked over the code but don't seem to find what's wrong.
Please change one line.
result += count > 1 ? message[n] + count : message[n];
If count is lower than 2, don't add count.
You can add a Conditional operator to only append the count if it is greater than 1.
result += message[n] + (count > 1 ? count : '');
Full code:
function compressedString(message) {
if (message.length == 0) {
return;
}
var result = '';
var count = 0;
for (var n = 0; n < message.length; n++) {
count++;
if (message[n] != message[n + 1]) {
result += message[n] + (count > 1 ? count : '');
count = 0;
}
}
return result;
}
console.log(compressedString('aabcc'));
Your function was actually returning: a2b1c2. If you want to return a2bc2 you just need an if to check if count is 1:
function compressedString(message) {
if (message.length == 0) {
return;
}
var result = "";
var count = 0;
for (var n = 0; n < message.length; n++) {
count++;
if (message[n] != message[n + 1]) {
if (count == 1)
result += message[n]
else {
result += message[n] + count;
}
count = 0;
}
}
return result;
}
Suppose you have arr1 = [a1,b2,c1];
and you want to convert it into [abbc]
Javascript accepts only numbers in for loop. So if you take the elements of this array individually, in the cast of characters it won't run except in the case of all the numbers it will run. But don't use +(element) operator. Since characters will throw a NaN.
So you can approach it so easily like this:
function check(string){
var new_string = "";
for(let i=0; i < string.length; i++){
let count = string[i];
for(var j=0; j< count; j++){
new_string = new_string + string[i];
}
}
console.log(new_string);
}
check("a2b3c2");
good luck

Get the sum from ASCII array

Write a function that accepts an array as argument. The function should loop through the array element and accumulate the sum of ASCII value of each character in each element and return the total.
function ASCIISuma(array) {
let suma = 0;
for(let i = 0; i < array.length; i++) {
let char_code = array[i].charCodeAt(0);
suma += char_code;
}
return suma;
}
It always shows me incorrect results.
You are only adding up the values of the first character of each element. To add them all:
function ASCIISuma(array) {
let suma = 0;
for(let i = 0; i < array.length; i++) {
for ( let j=0; j < array[i].length; j++ ) {
let char_code = array[i].charCodeAt(j);
suma += char_code;
}
}
}
return suma;
}
Function to return the sum
of the ascii values of the characters
which are present at prime positions
function isPrime(n){
if (n == 0 || n == 1)
return false;
for (let i = 2; i * i <= n; i++)
if (n % i == 0)
return false;
return true;
}
function sumAscii(str, n){
let sum = 0;
// For every character
for (let i = 0; i < n; i++) {
// If current position is prime
// then add the ASCII value of the
// character at the current position
if (isPrime(i + 1))
sum += str.charCodeAt(i);
}
return sum;
}
let str = "geeksforgeeks";
let n = str.length;
document.write(sumAscii(str, n));

Print all possibilities by rotating a string in Javascript

How to rotate a string in javascript and print the rotated versions of string without using any javascript functions, only for loops.
Given a string:
"hell"
Output:
"lhel", "llhe", "ellh", "hell"
I have tried but not succeded
var str1 = "hell";
let i = 0;
let len = str1.length - 1;
let temp;
for (let j = 0; j < len+1; j++) {
temp = str1[len]
while (i < len) {
console.log(str1[i]);
temp += str1[i];
i++;
}
console.log(temp);
//console.log(typeof temp, typeof str1)
str1 = temp;
}
You are almost there ! There is one thing missing, i should be reset at each iteration of the for loop, otherwise, the while (i < len) will be "played" only once :
var str1 = "hell";
let len = str1.length - 1;
let temp;
for (let j = 0; j < len+1; j++) {
let i = 0; // <-------------------- notice this
temp = str1[len]
while (i < len) {
//console.log(str1[i]);
temp += str1[i];
i++;
}
console.log(temp);
//console.log(typeof temp, typeof str1)
str1 = temp;
}
You could take a nested loop and get the characters at the position of i and j and take the reminder operator % for preventing characters outside of the string.
var string = "hell",
i, j,
temp;
for (i = 0; i < string.length; i++) {
temp = '';
for (j = 1; j <= string.length; j++) temp += string[(i + j) % string.length];
console.log(temp);
}
You can try this method. Basically you have two loops the first loop with (i) is for the possibilities the second one is for the shifting
var strValue = "hell";
var temp;
for(var i = 0; i < strValue.length; i++){
temp = "";
for(var j = 1; j < strValue.length; j++){
temp += strValue[j];
}
temp += strValue[0]
strValue = temp;
console.log(strValue)
}
In first loop add all symbols which indexes are greater then amount of shift steps (i in this case).
And add rest symbols after it the second loop.
const str = 'hello';
for (let i = 0; i < str.length; i++) {
let shifted = '';
for (let j = i; j < str.length; j++) {
shifted += str[j];
}
for (let j = 0; j < i; j++) {
shifted += str[j];
}
console.log(shifted);
}
i know this has already been answered so.. this is how i'd do it.
maybe you can learn from it.
const str = "hell";
// this loop will set the offset. so if it's 1, "hell" will become "ellh"
for (let offset = 0; offset < str.length; offset++) {
// this will contain the final string
let output = "";
// here we iterate through all the characters
for (let index = 0; index < str.length; index++) {
// and use modulo to switch 5 to 1 (in case length is 4)
output += str[(index + offset) % str.length];
}
// there we go
console.log(output);
}
let str = 'hell';
for(let i=0;i<str.length;i++){
str = str.substring(1,str.length) + str[0];
console.log(str);
}

Split string without any built-in functions

I need a function that works like split
var string = "a|b|c"
console.log(string.split('|'))
to get a string and split it using loop
function splitstr(str, charToSplit){
}
I want the output of ('a|b|c', '|') to be ["a", "b", "c"]
Here is a slightly simpler solution that works correctly:
function splitStr(str, separator) {
const parts = [];
let nextPart = '';
for (let i = 0; i <= str.length; i++) {
if (str[i] === separator || i === str.length) {
parts[parts.length] = nextPart;
nextPart = '';
} else {
nextPart += str[i]
}
}
return parts;
}
console.log(splitStr("abc|abcd|ac", "|"));
You can use the code below.
This code had 8 steps to it.
Loops through the string
Checks if the current item is equal to charToSplit
If it is, it loops through the values in between startIndex and your current index (excluding your current index, which is the character you want to split on)
It first sets the value of output[currentIndex] to an empty string (since using += on something that doesn't exist doesn't work correctly
Then it adds the current letter you are on to output
startIndex is set to your current index + 1 (which is the character after the character that you want to split on)
currentIndex is increased by 1 since you're now on the next set of values
Finally, the code returns output
Note: The final extra loop after the first loop is there to add the last value to your output array.
function splitstr(str, charToSplit) {
var output = [];
var currentIndex = 0;
var startIndex = 0;
for (var i = 0; i < str.length; i++) {
if (str[i] == charToSplit) {
output[currentIndex] = "";
for (var x = startIndex; x < i; x++) {
output[currentIndex] += str[x];
}
startIndex = i + 1;
currentIndex++;
}
}
output[currentIndex] = "";
for (var i = startIndex; i < str.length; i++) {
output[currentIndex] += str[i];
}
return output;
}
console.log(splitstr("abc|abcd|ac", "|"));

longest substring of non repeating characters javascript

The problems asks "given a string, find the longest non-repeating sub-string without repeating characters". I am a little stumped why returning my code is not working for the string "dvdf" for example. Here is my code :
function lengthOfLongestSubstring(check) {
var letters = check.split("");
var max = 0;
var result = [];
for (var i = 0; i < letters.length; i++) {
var start = i
if (result.indexOf(letters[i]) === -1) {
result.push(letters[i])
} else {
i = i - 1
result = []
}
if (max === 0 || max < result.length) {
max = result.length
}
}
return max
}
This implementation gives the correct result for "dvdf".
It adds characters to current_string while there is no duplicate. When you find a duplicate cut current_string to the point of the duplicate. max is the max length current_string had at any time. This logic seems correct to me so I think it's correct.
function lengthOfLongestSubstring(string) {
var max = 0, current_string = "", i, char, pos;
for (i = 0; i < string.length; i += 1) {
char = string.charAt(i);
pos = current_string.indexOf(char);
if (pos !== -1) {
// cut "dv" to "v" when you see another "d"
current_string = current_string.substr(pos + 1);
}
current_string += char;
max = Math.max(max, current_string.length);
}
return max;
}
lengthOfLongestSubstring("dvdf"); // 3
The value of current_string in each round is "", "d", "dv", "vd", "vdf".
By replacing the result array with a map storing the last index for each encountered character, you can modify the loop body to jump back to one after the last index of an identical character and continue your search from there instead of just restarting from the current position via currently i = i - 1 which fails in cases such as 'dvdf':
Below is your code with changes to accommodate a map in place of an array:
function lengthOfLongestSubstring(check) {
var letters = check.split("");
var max = 0;
var result = new Map();
var start = 0;
for (var i = 0; i < letters.length; i++) {
if (!result.has(letters[i])) {
result.set(letters[i], i);
} else {
i = result.get(letters[i]);
result.clear();
}
if (max < result.size) {
max = result.size;
}
}
return max;
}
// Example:
console.log(lengthOfLongestSubstring("dvdf")); // 3
Here's a solution using Sliding window and HashMap.
var lengthOfLongestSubstring = function(str) {
if (!!!str.length || typeof str !== 'string') return 0;
if (str.length == 1) return 1;
let hashTable = {};
let longestSubstringLength = 0;
let start = 0;
for (let i = 0; i < str.length; i++) {
if (hashTable[str[i]] !== undefined && hashTable[str[i]] >= start) {
start = hashTable[str[i]] + 1;
}
hashTable[str[i]] = i;
longestSubstringLength = Math.max(longestSubstringLength, (i - start + 1))
}
return longestSubstringLength;
}
I figured out an easier solution:
function longestSubstring(str) {
let left = 0;
let max = 0;
let result = new Set();
for (let r = 0; r < str.length; r++) {
//The code will check for an existing item on the set
// If found, all the previously saved items will be deleted
// the set will return to being empty
while (result.has(str[r])) {
result.delete(str[left]);
left += 1;
}
result.add(str[r]);
max = Math.max(max, r - left + 1);
}
console.log(result);
return max;
}
console.log(longestSubstring('abcabccbc')); //3
Today (January 7th, 2021) this was the Leetcode question of the day. I initially used a solution very similar to the selected answer. Performance was okay but after reviewing the answer solution documentation I rewrote my answer using the sliding window technique (examples were only in Java and Python) since I was curious about how much of a performance improvement this would result in. It is slightly more performant (144ms versus 160ms) and has a lower memory footprint (42mb versus 44.9mb):
function lengthOfLongestSubstring(s: string): number {
let stringLength = s.length;
let maxLength = 0;
const charMap = new Map();
let pos = 0;
for (let i = 0; i < stringLength; i++) {
if (charMap.has(s[i])) {
pos = Math.max(charMap.get(s[i]), pos);
}
maxLength = Math.max(maxLength, i - pos + 1);
charMap.set(s[i], i + 1);
}
return maxLength;
}
console.log(lengthOfLongestSubstring("dvdf"));
Try this:
function lengthOfLongestSubstring (str) {
const map = new Map();
let max = 0;
let left = 0;
for (let right = 0; right < str.length; right++) {
const char = str[right];
if (map.get(char) >= left) left = map.get(char) + 1;
else max = Math.max(max, right - left + 1);
map.set(char, right);
}
return max;
}
You can try this:
function lengthOfLongestSubstring(str) {
let longest = "";
for (let i = 0; i < str.length; i++) {
if (longest.includes(str[i])) {
return longest.length
} else {
longest += str[i];
}
}
return longest.length;
}
console.log(lengthOfLongestSubstring("abcabcbb"));
console.log(lengthOfLongestSubstring("bbbbb"));
console.log(lengthOfLongestSubstring("abcdef"));
console.log(lengthOfLongestSubstring(""));
reset i to i -1 is incorrect. you need another loop inside the for loop. you try something like this (i didn't check the index carefully).
function lengthOfLongestSubstring(check){
var letters = check.split("");
var max = 0;
for (var i = 0; i < letters.length; i++) {
var result = [];
var j = i;
for(;j < letters.length; j++) {
if (result.indexOf(letters[j]) === -1) {
result.push(letters[j]);
} else {
break;
}
}
if(j - i > max) {
max = j - i;
}
}
return max;
}
You can try sliding window pattern to solve this problem.
function lengthOfLongestSubstring(str) {
let longest = 0;
let longestStr = "";
let seen = {};
let start = 0;
let next = 0;
while (next < str.length) {
// Take current character from string
let char = str[next];
// If current character is already present in map
if (seen[char]) {
// Check if start index is greater than current character's last index
start = Math.max(start, seen[char]);
}
// If new substring is longer than older
if (longest < next - start + 1) {
longest = next - start + 1;
// Take slice of longer substring
longestStr = str.slice(start, next + 1);
}
// Update current characters index
seen[char] = next + 1;
// Move to next character
next++;
}
console.log(str, "->", longestStr, "->", longest);
return longest;
}
lengthOfLongestSubstring("dvdfvev");
lengthOfLongestSubstring("hello");
lengthOfLongestSubstring("1212312344");
Find Longest Unique Substring using Map Method
var str = "aaabcbdeaf";
var start = 0;
var map = new Map();
var maxLength = 0;
var longStr = '';
for(next =0; next< str.length ; next++){
if(map.has(str[next])){
map.set(str[next],map.get(str[next])+1);
start = Math.max(start,map.get(str[next]));
}
if(maxLength < next-start+1){
maxLength = next-start+1;
longStr = str.slice(start,next+1);
}
map.set(str[next],next);
}
console.log(longStr);
You can try something like that:
function maxSubstring(s) {
const array = []
const lengthS = s.length
const pusher = (value) => {
if (value !== '') {
if (array.length > 0) {
if (array.indexOf(value) === -1) {
array.push(value)
}
} else {
array.push(value)
}
}
}
pusher(s)
for (const [index, value] of s.split('').entries()) {
let length = lengthS
let string = s
const indexO = s.indexOf(value)
pusher(value)
while (length > indexO) {
pusher(string.slice(index-1, length + 1))
length = --length
}
string = s.slice(index, lengthS)
}
array.sort()
return array.pop()
}
console.log(maxSubstring('banana'))
console.log(maxSubstring('fgjashore'))
console.log(maxSubstring('xyzabcd'))
Find Longest unique substring without using MAP(). Just simple slice().
The same can be used to return longest unique string.
Just replace "return max => return str"
const string = "dvdf";
var lengthOfLongestSubstring = function() {
if(string.length == 1) return 1;
if(string.length == 0) return 0;
let max = 0,i = 0, str = "";
while(i < string.length){
const index = str.indexOf(string.charAt(i));
if(index > -1) {
// s = "fiterm".slice(1,4) => ite
str = str.slice(index + 1, string.length);
}
str += string.charAt(i);
max = Math.max(str.length, max);
i++;
}
return max;
};
Logest unqiue substring:
function lengthOfLongestSubstring(s) {
if(s.length < 2) {
return s.length;
}
let longestLength = 1;
let currentStr = '';
for(let i=0 ; i < s.length ; i++){
if(currentStr.includes(s.charAt(i))){
let firstSeen = currentStr.indexOf(s.charAt(i));
currentStr = currentStr.substring(firstSeen+1,currentStr.length);
}
currentStr += s.charAt(i);
longestLength = Math.max(currentStr.length,longestLength);
}
return longestLength;
};
One liner with reduce method.
const subStrOfUniqueChar = str => [...str].reduce((p,c) => ( p.includes(c) ? (p += c, p.substr(p.indexOf(c)+1)) : p += c),'');
console.log(subStrOfUniqueChar('dvdf').length);
function lengthOfLongestSubstring(s: string): number {
const arr = s.split("");
let longest = 0;
const set: Set<string> = new Set();
for (let i = 0; i < arr.length; i++) {
set.add(arr[i]);
let tryIndex = i + 1;
while (arr[tryIndex] && !set.has(arr[tryIndex])) {
set.add(arr[tryIndex]);
tryIndex++;
}
if (set.size > longest) {
longest = set.size;
}
set.clear();
}
return longest;
}
I wanted to toss my hat in this ring because I feel like I've found a pretty creative solution to this. No if/else blocks are needed as the substring.indexOf() will attempt to find the matching string character in the array and delete the indexes of the array up to, and including, the match (+1). If an indexOf() call finds no match it will return a -1, which added to +1 becomes a .splice(0,0) which will remove nothing. The final Math check factors in the last character addition in the loop to determine which outcome is higher.
const findSubstring = string => {
let substring = [];
let maxCount = 0;
for (let i = 0; i < string.length; i++) {
maxCount = Math.max(substring.length, maxCount);
substring.splice(0, substring.indexOf(string[i]) + 1);
substring.push(string[i]);
}
maxCount = Math.max(substring.length, maxCount);
return maxCount;
}
uses sliding window concept
function lengthOfLongestSubstring(s) {
var letters = s.split("");
var subStr = "";
var result = [];
var len = 0;
let maxLen = 0;
for (var i = 0; i < letters.length; i++) {
const position = result.indexOf(letters[i]);
if (position === -1) {
result.push(letters[i]);
len += 1;
} else if (letters[i]) {
result = result.splice(position + 1);
len = result.length + 1;
result.push(letters[i]);
}
maxLen = len > maxLen ? len : maxLen;
}
return maxLen;
}
console.log(lengthOfLongestSubstring(" "));
Sliding Window Technique O(n)
you can use hash or Map in
loop through string char
Maintain dictionary of unique char
if char exist in memory take clear hash update the count in longest variable and clear count
start from first repeated char + 1 again.
var lengthOfLongestSubstring = function(s) {
if(s.length<2) return s.length;
let longest = 0;
let count=0;
let hash={}
for (let i = 0; i < s.length; i++) {
//If char exist in hash
if(hash[s[i]]!=undefined){
i=hash[s[i]];
hash={}
longest = Math.max(longest, count);
count = 0;
}else{
hash[s[i]]=i
count = count+1;
}
}
return Math.max(longest, count);
};
console.log(lengthOfLongestSubstring("abcabcbb"))
console.log(lengthOfLongestSubstring("au"))

Categories