longest substring of non repeating characters javascript - 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"))

Related

Character with longest consecutive repetition

i think i have wirtten the correct code for the problem only one thing and it that i return the first longest sequence how can i alter that to return the last maximum sequence?
an example from codewars editor :
for input '00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'
Expected: ['c', 19], instead got: ['0', 19]
here is my code:
function longestRepetition(s) {
var count = 0;
var temp = s.charAt(0);
var arr = [];
for (var i = 0; i < s.length; i++) {
if (temp === s.charAt(i)) {
count++
temp = s.charAt(i)
}
else {
temp = s.charAt(i);
arr.push(count)
count = 1;
}
if(i==s.length-1)
arr.push(count);
}
if(arr.length>0)
{
var Max=arr[0]
for(var i=0;i<arr.length;i++)
{
if(Max<=arr[i])
Max=arr[i];
}
}
else var Max=0;
var mindex=arr.indexOf(Max);
return [s.charAt(mindex),Max]
}
I think this would be easier with a regular expression. Match any character, then backreference that character as many times as you can.
Then, you'll have an array of all the sequential sequences, eg ['000', 'aaaaa']. Map each string to its length and pass into Math.max, and you'll know how long the longest sequence is.
Lastly, filter the sequences by those which have that much length, and return the last item in the filtered array:
function longestRepetition(s) {
const repeatedChars = s.match(/(.)\1*/g);
const longestLength = Math.max(...repeatedChars.map(str => str.length));
const longestChars = repeatedChars.filter(str => str.length === longestLength);
return [longestChars.pop(), longestLength];
}
console.log(longestRepetition('00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'));
The issue in your code is that minindex is an index in your arr, but that index has nothing to do with s. So s.charAt(minindex) makes no sense. You should maintain for which character you had found the count. For instance you could push in arr both the count and the corresponding character (as a subarray with two values). Then the rest of your code would only need little modification to make it work.
Applying this idea to your code without changing anything else, we get this:
function longestRepetition(s) {
var count = 0;
var temp = s.charAt(0);
var arr = [];
for (var i = 0; i < s.length; i++) {
if (temp === s.charAt(i)) {
count++
temp = s.charAt(i) // Not necessary: was already equal
}
else {
arr.push([temp, count]); // <--- pair, BEFORE changing temp
temp = s.charAt(i);
count = 1;
}
if(i==s.length-1)
arr.push([temp, count]); // <---
}
if(arr.length>0)
{
var Max=arr[0]; // <-- Max is now a pair of char & count
for(var i=0;i<arr.length;i++)
{
if(Max[1]<arr[i][1]) // Comparison changed to just less-than
Max=arr[i];
}
}
else Max=[null, 0]; // Must be a pair here also
return Max; // Just return the pair
}
console.log(longestRepetition('00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'));
But you can do the same with less code:
function longestRepetition(s) {
let result = [null, 0]; // pair of character and count
for (var i = 0; i < s.length; null) {
let start = i++;
while (i < s.length && s[i] === s[start]) i++; // Find end of series
if (i - start > result[1]) result = [s[start], i - start];
}
return result;
}
console.log(longestRepetition('00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'));
The solution below answers the question with O(n) runtime:
function longestRepetition(s) {
let count = s.length > 0 ? 1 : 0
let char = s.length > 0 ? s[0] : ''
for (let string_i = 0; string_i < s.length - 1; string_i += 1) {
// keep track of current_char
let current_char = s[string_i]
let next_char = s[string_i + 1]
// while the next char is same as current_char
let tracker = 1
while (current_char === next_char) {
// add one to tracker
tracker += 1
string_i += 1
next_char = s[string_i + 1]
}
// if tracker greater than count
if (tracker > count) {
// returned char = current char
// count =tracker
count = tracker;
char = current_char;
}
}
return [char, count]
}
console.log(longestRepetition("bbbaaabaaaa"))//, ["a",4]

Counting the number of duplicates with nested loops. How to escape from comparing two chars with the same index

Function that will return the count of distinct case-insensitive alphabetic characters and numeric digits that occur more than once in the input string.
"abcde" -> 0 # no characters repeats more than once
"indivisibility" -> 1 # 'i' occurs six times
rs twice
The problem is that each iteration loops meet on the same char and compare it. How can I avoid it?
function duplicateCount(text){
var texT = text.toLowerCase();
var count = 0;
var total = 0;
for(var i = 0; i < texT.length; i++ ){
var char = texT[i];
if(count > 1){
total = total + 1;
}
for ( var j = 0; j < texT.length; j++){
var char2 = texT[j];
if(char === char2){
count = count + 1;
}
}
}
return total;
}
duplicateCount('kBHhJkj8l8');
function duplicateCount(text){
var texT = text.toLowerCase();
const obj = {};
for(var i = 0; i < texT.length; i++ ){
if(obj[texT[i]]) {
obj[texT[i]] += 1;
}
else {
obj[texT[i]] = 1;
}
}
let total = 0;
Object.keys(obj).forEach(key => {
if(obj[key] != 1){
total += 1;
}
})
return total;
}
console.log(duplicateCount('kBHhJkj8l8'));
Use a hash to keep track of the visited chars, and skip the comparison if you already have a duplicate char (at least 2):
function duplicateCount(text){
text = text.toLowerCase();
const occurrences = {};
for (let char of text) {
if (occurrences[char] === 2) continue; // skip comparison
occurrences[char] = ~~ occurrences[char] + 1;
}
return Object.values(occurrences)
.filter((occurrence) => occurrence > 1)
.length;
}
console.log(duplicateCount('kBHhJkj8l88888'));

Longest palindrome in a string

I wrote the following function to find the longest palindrome in a string. It works fine but it won't work for words like "noon" or "redder". I fiddled around and changed the first line in the for loop from:
var oddPal = centeredPalindrome(i, i);
to
var oddPal = centeredPalindrome(i-1, i);
and now it works, but I'm not clear on why. My intuition is that if you are checking an odd-length palindrome it will have one extra character in the beginning (I whiteboarded it out and that's the conclusion I came to). Am I on the right track with my reasoning?
var longestPalindrome = function(string) {
var length = string.length;
var result = "";
var centeredPalindrome = function(left, right) {
while (left >= 0 && right < length && string[left] === string[right]) {
//expand in each direction.
left--;
right++;
}
return string.slice(left + 1, right);
};
for (var i = 0; i < length - 1; i++) {
var oddPal = centeredPalindrome(i, i);
var evenPal = centeredPalindrome(i, i);
if (oddPal.length > result.length)
result = oddPal;
if (evenPal.length > result.length)
result = evenPal;
}
return "the palindrome is: " + result + " and its length is: " + result.length;
};
UPDATE:
After Paul's awesome answer, I think it makes sense to change both variables for clarity:
var oddPal = centeredPalindrome(i-1, i + 1);
var evenPal = centeredPalindrome(i, i+1);
You have it backwards - if you output the "odd" palindromes (with your fix) you'll find they're actually even-length.
Imagine "noon", starting at the first "o" (left and right). That matches, then you move them both - now you're comparing the first "n" to the second "o". No good. But with the fix, you start out comparing both "o"s, and then move to both "n"s.
Example (with the var oddPal = centeredPalindrome(i-1, i); fix):
var longestPalindrome = function(string) {
var length = string.length;
var result = "";
var centeredPalindrome = function(left, right) {
while (left >= 0 && right < length && string[left] === string[right]) {
//expand in each direction.
left--;
right++;
}
return string.slice(left + 1, right);
};
for (var i = 0; i < length - 1; i++) {
var oddPal = centeredPalindrome(i, i + 1);
var evenPal = centeredPalindrome(i, i);
if (oddPal.length > 1)
console.log("oddPal: " + oddPal);
if (evenPal.length > 1)
console.log("evenPal: " + evenPal);
if (oddPal.length > result.length)
result = oddPal;
if (evenPal.length > result.length)
result = evenPal;
}
return "the palindrome is: " + result + " and its length is: " + result.length;
};
console.log(
longestPalindrome("nan noon is redder")
);
This will be optimal if the largest palindrome is found earlier.
Once its found it will exit both loops.
function isPalindrome(s) {
//var rev = s.replace(/\s/g,"").split('').reverse().join(''); //to remove space
var rev = s.split('').reverse().join('');
return s == rev;
}
function longestPalind(s) {
var maxp_length = 0,
maxp = '';
for (var i = 0; i < s.length; i++) {
var subs = s.substr(i, s.length);
if (subs.length <= maxp_length) break; //Stop Loop for smaller strings
for (var j = subs.length; j >= 0; j--) {
var sub_subs = subs.substr(0, j);
if (sub_subs.length <= maxp_length) break; // Stop loop for smaller strings
if (isPalindrome(sub_subs)) {
maxp_length = sub_subs.length;
maxp = sub_subs;
}
}
}
return maxp;
}
Here is another take on the subject.
Checks to make sure the string provided is not a palindrome. If it is then we are done. ( Best Case )
Worst case 0(n^2)
link to
gist
Use of dynamic programming. Break each problem out into its own method, then take the solutions of each problem and add them together to get the answer.
class Palindrome {
constructor(chars){
this.palindrome = chars;
this.table = new Object();
this.longestPalindrome = null;
this.longestPalindromeLength = 0;
if(!this.isTheStringAPalindrome()){
this.initialSetupOfTableStructure();
}
}
isTheStringAPalindrome(){
const reverse = [...this.palindrome].reverse().join('');
if(this.palindrome === reverse){
this.longestPalindrome = this.palindrome;
this.longestPalindromeLength = this.palindrome.length;
console.log('pal is longest', );
return true;
}
}
initialSetupOfTableStructure(){
for(let i = 0; i < this.palindrome.length; i++){
for(let k = 0; k < this.palindrome.length; k++){
this.table[`${i},${k}`] = false;
}
}
this.setIndividualsAsPalindromes();
}
setIndividualsAsPalindromes(){
for(let i = 0; i < this.palindrome.length; i++){
this.table[`${i},${i}`] = true;
}
this.setDoubleLettersPlaindrome();
}
setDoubleLettersPlaindrome(){
for(let i = 0; i < this.palindrome.length; i++){
const firstSubstring = this.palindrome.substring(i, i + 1);
const secondSubstring = this.palindrome.substring(i+1, i + 2);
if(firstSubstring === secondSubstring){
this.table[`${i},${i + 1}`] = true;
if(this.longestPalindromeLength < 2){
this.longestPalindrome = firstSubstring + secondSubstring;
this.longestPalindromeLength = 2;
}
}
}
this.setAnyPalindromLengthGreaterThan2();
}
setAnyPalindromLengthGreaterThan2(){
for(let k = 3; k <= this.palindrome.length; k++){
for(let i = 0; i <= this.palindrome.length - k; i++){
const j = i + k - 1;
const tableAtIJ = this.table[`${i+1},${j-1}`];
const stringToCompare = this.palindrome.substring(i, j +1);
const firstLetterInstringToCompare = stringToCompare[0];
const lastLetterInstringToCompare = [...stringToCompare].reverse()[0];
if(tableAtIJ && firstLetterInstringToCompare === lastLetterInstringToCompare){
this.table[`${i},${j}`] = true;
if(this.longestPalindromeLength < stringToCompare.length){
this.longestPalindrome = stringToCompare;
this.longestPalindromeLength = stringToCompare.length;
}
}
}
}
}
printLongestPalindrome(){
console.log('Logest Palindrome', this.longestPalindrome);
console.log('from /n', this.palindrome );
}
toString(){
console.log('palindrome', this.palindrome);
console.log(this.table)
}
}
// const palindrome = new Palindrome('lollolkidding');
// const palindrome = new Palindrome('acbaabca');
const palindrome = new Palindrome('acbaabad');
palindrome.printLongestPalindrome();
//palindrome.toString();
function longestPalindrome(str){
var arr = str.split("");
var endArr = [];
for(var i = 0; i < arr.length; i++){
var temp = "";
temp = arr[i];
for(var j = i + 1; j < arr.length; j++){
temp += arr[j];
if(temp.length > 2 && temp === temp.split("").reverse().join("")){
endArr.push(temp);
}
}
}
var count = 0;
var longestPalindrome = "";
for(var i = 0; i < endArr.length; i++){
if(count >= endArr[i].length){
longestPalindrome = endArr[i-1];
}
else{
count = endArr[i].length;
}
}
console.log(endArr);
console.log(longestPalindrome);
return longestPalindrome;
}
longestPalindrome("abracadabra"));
let str = "HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE";
let rev = str.split("").reverse().join("").trim();
let len = str.length;
let a="";
let result = [];
for(let i = 0 ; i < len ; i++){
for(let j = len ; j > i ; j--){
a = rev.slice(i,j);
if(str.includes(a)){
result.push(a);
break;
}
}
}
result.sort((a,b) => { return b.length - a.length})
let logPol = result.find((value)=>{
return value === value.split('').reverse().join('') && value.length > 1
})
console.log(logPol);
function longest_palindrome(s) {
if (s === "") {
return "";
}
let arr = [];
let _s = s.split("");
for (let i = 0; i < _s.length; i++) {
for (let j = 0; j < _s.length; j++) {
let word = _s.slice(0, j + 1).join("");
let rev_word = _s
.slice(0, j + 1)
.reverse()
.join("");
if (word === rev_word) {
arr.push(word);
}
}
_s.splice(0, 1);
}
let _arr = arr.sort((a, b) => a.length - b.length);
for (let i = 0; i < _arr.length; i++) {
if (_arr[arr.length - 1].length === _arr[i].length) {
return _arr[i];
}
}
}
longest_palindrome('bbaaacc')
//This code will give you the first longest palindrome substring into the string
var longestPalindrome = function(string) {
var length = string.length;
var result = "";
var centeredPalindrome = function(left, right) {
while (left >= 0 && right < length && string[left] === string[right]) {
//expand in each direction.
left--;
right++;
}
return string.slice(left + 1, right);
};
for (var i = 0; i < length - 1; i++) {
var oddPal = centeredPalindrome(i, i + 1);
var evenPal = centeredPalindrome(i, i);
if (oddPal.length > 1)
console.log("oddPal: " + oddPal);
if (evenPal.length > 1)
console.log("evenPal: " + evenPal);
if (oddPal.length > result.length)
result = oddPal;
if (evenPal.length > result.length)
result = evenPal;
}
return "the palindrome is: " + result + " and its length is: " + result.length;
};
console.log(longestPalindrome("n"));
This will give wrong output so this condition need to be taken care where there is only one character.
public string LongestPalindrome(string s) {
return LongestPalindromeSol(s, 0, s.Length-1);
}
public static string LongestPalindromeSol(string s1, int start, int end)
{
if (start > end)
{
return string.Empty;
}
if (start == end)
{
char ch = s1[start];
string s = string.Empty;
var res = s.Insert(0, ch.ToString());
return res;
}
if (s1[start] == s1[end])
{
char ch = s1[start];
var res = LongestPalindromeSol(s1, start + 1, end - 1);
res = res.Insert(0, ch.ToString());
res = res.Insert(res.Length, ch.ToString());
return res;
}
else
{
var str1 = LongestPalindromeSol(s1, start, end - 1);
var str2 = LongestPalindromeSol(s1, start, end - 1);
if (str1.Length > str2.Length)
{
return str1;
}
else
{
return str2;
}
}
}
This is in JS ES6. much simpler and works for almost all words .. Ive tried radar, redder, noon etc.
const findPalindrome = (input) => {
let temp = input.split('')
let rev = temp.reverse().join('')
if(input == rev){
console.log('Palindrome', input.length)
}
}
//i/p : redder
// "Palindrome" 6

Longest substring in alphabetical order Javascript

Seeing all the people talking about longest substring in alphabetical order in Python, I have decided to try it in JS.
The function should look for the longest substring inside a given string, where letters are ordered alphabetically.
Here is what I have:
var s = 'azcbobobegghakl'
function substringChecker(s) {
var longestSub = "";
for (var i = 0; i < s.length; i++) {
var count = 0;
var currSub = "";
while((i+count)<=s.length){
var curr = i+count;
var next = curr+1;
var prev = curr-1;
if(curr !== s.length-1) {
if(s[curr] <= s[next]){
currSub += s[curr]
} else {
break;
}
} else {
if(s[curr]>s[prev]) {
currSub += s[curr];
}
}
count++;
}
if(currSub.length >= longestSub.length) {
longestSub = currSub;
}
};
return longestSub;
}
var result = substringChecker(s);;
console.log(result);
The funny thing it works great for all test cases I can come up with, but this one. The result should be "beggh" but it is "begg" instead. Why is the h not showing up, what am I missing?
The algorithm can be linear, I think you are overcomplicating it placing loops inside loops.
I would use something like
function substringChecker(s) {
var longestSub = "",
length = 0,
start = 0,
prev = s[0];
for (var i = 1; i <= s.length; ++i) {
if(i == s.length || s[i] < prev) {
if(length < i-start) {
longestSub = s.substring(start, i);
length = i-start;
}
start = i;
}
prev = s[i];
};
return longestSub;
}
document.write(substringChecker('azcbobobegghakl'));
first I made list of A-z
then check each letter and compare it with the next letter and save it in subString and...
function longest(str) {
//handle the case str is just one letter
if (str.length === 1) return str;
// create a list of alphabet A to Z
const alphabets = [...Array(26)].map(_ => String.fromCharCode(i++), (i = 97));
let longString = "";
let subSting = "";
for (let x = 0; x < str.length; x++) {
let char = str.charAt(x);
const nextChar = str.charAt(x + 1);
let charIndex = alphabets.findIndex(alphabet => alphabet === char);
let nextCharIndex = alphabets.findIndex(alphabet => alphabet === nextChar);
if (nextCharIndex >= charIndex) {
subSting = subSting + nextChar;
} else {
if (!subSting.length) {
subSting = subSting + char;
}
longString = subSting.length > longString.length ? subSting : longString;
subSting = "";
}
}
return longString;
}
console.log(longest("zyba"));

Find the characters in a string which are not duplicated

I have to make a function in JavaScript that removes all duplicated letters in a string. So far I've been able to do this: If I have the word "anaconda" it shows me as a result "anaconda" when it should show "cod". Here is my code:
function find_unique_characters( string ){
var unique='';
for(var i=0; i<string.length; i++){
if(unique.indexOf(string[i])==-1){
unique += string[i];
}
}
return unique;
}
console.log(find_unique_characters('baraban'));
We can also now clean things up using filter method:
function removeDuplicateCharacters(string) {
return string
.split('')
.filter(function(item, pos, self) {
return self.indexOf(item) == pos;
})
.join('');
}
console.log(removeDuplicateCharacters('baraban'));
Working example:
function find_unique_characters(str) {
var unique = '';
for (var i = 0; i < str.length; i++) {
if (str.lastIndexOf(str[i]) == str.indexOf(str[i])) {
unique += str[i];
}
}
return unique;
}
console.log(find_unique_characters('baraban'));
console.log(find_unique_characters('anaconda'));
If you only want to return characters that appear occur once in a string, check if their last occurrence is at the same position as their first occurrence.
Your code was returning all characters in the string at least once, instead of only returning characters that occur no more than once. but obviously you know that already, otherwise there wouldn't be a question ;-)
Just wanted to add my solution for fun:
function removeDoubles(string) {
var mapping = {};
var newString = '';
for (var i = 0; i < string.length; i++) {
if (!(string[i] in mapping)) {
newString += string[i];
mapping[string[i]] = true;
}
}
return newString;
}
With lodash:
_.uniq('baraban').join(''); // returns 'barn'
You can put character as parameter which want to remove as unique like this
function find_unique_characters(str, char){
return [...new Set(str.split(char))].join(char);
}
function find_unique_characters(str, char){
return [...new Set(str.split(char))].join(char);
}
let result = find_unique_characters("aaaha ok yet?", "a");
console.log(result);
//One simple way to remove redundecy of Char in String
var char = "aaavsvvssff"; //Input string
var rst=char.charAt(0);
for(var i=1;i<char.length;i++){
var isExist = rst.search(char.charAt(i));
isExist >=0 ?0:(rst += char.charAt(i) );
}
console.log(JSON.stringify(rst)); //output string : avsf
For strings (in one line)
removeDuplicatesStr = str => [...new Set(str)].join('');
For arrays (in one line)
removeDuplicatesArr = arr => [...new Set(arr)]
Using Set:
removeDuplicates = str => [...new Set(str)].join('');
Thanks to David comment below.
DEMO
function find_unique_characters( string ){
unique=[];
while(string.length>0){
var char = string.charAt(0);
var re = new RegExp(char,"g");
if (string.match(re).length===1) unique.push(char);
string=string.replace(re,"");
}
return unique.join("");
}
console.log(find_unique_characters('baraban')); // rn
console.log(find_unique_characters('anaconda')); //cod
​
var str = 'anaconda'.split('');
var rmDup = str.filter(function(val, i, str){
return str.lastIndexOf(val) === str.indexOf(val);
});
console.log(rmDup); //prints ["c", "o", "d"]
Please verify here: https://jsfiddle.net/jmgy8eg9/1/
Using Set() and destructuring twice is shorter:
const str = 'aaaaaaaabbbbbbbbbbbbbcdeeeeefggggg';
const unique = [...new Set([...str])].join('');
console.log(unique);
Yet another way to remove all letters that appear more than once:
function find_unique_characters( string ) {
var mapping = {};
for(var i = 0; i < string.length; i++) {
var letter = string[i].toString();
mapping[letter] = mapping[letter] + 1 || 1;
}
var unique = '';
for (var letter in mapping) {
if (mapping[letter] === 1)
unique += letter;
}
return unique;
}
Live test case.
Explanation: you loop once over all the characters in the string, mapping each character to the amount of times it occurred in the string. Then you iterate over the items (letters that appeared in the string) and pick only those which appeared only once.
function removeDup(str) {
var arOut = [];
for (var i=0; i < str.length; i++) {
var c = str.charAt(i);
if (c === '_') continue;
if (str.indexOf(c, i+1) === -1) {
arOut.push(c);
}
else {
var rx = new RegExp(c, "g");
str = str.replace(rx, '_');
}
}
return arOut.join('');
}
I have FF/Chrome, on which this works:
var h={};
"anaconda".split("").
map(function(c){h[c] |= 0; h[c]++; return c}).
filter(function(c){return h[c] == 1}).
join("")
Which you can reuse if you write a function like:
function nonRepeaters(s) {
var h={};
return s.split("").
map(function(c){h[c] |= 0; h[c]++; return c}).
filter(function(c){return h[c] == 1}).
join("");
}
For older browsers that lack map, filter etc, I'm guessing that it could be emulated by jQuery or prototype...
This code worked for me on removing duplicate(repeated) characters from a string (even if its words separated by space)
Link: Working Sample JSFiddle
/* This assumes you have trim the string and checked if it empty */
function RemoveDuplicateChars(str) {
var curr_index = 0;
var curr_char;
var strSplit;
var found_first;
while (curr_char != '') {
curr_char = str.charAt(curr_index);
/* Ignore spaces */
if (curr_char == ' ') {
curr_index++;
continue;
}
strSplit = str.split('');
found_first = false;
for (var i=0;i<strSplit.length;i++) {
if(str.charAt(i) == curr_char && !found_first)
found_first = true;
else if (str.charAt(i) == curr_char && found_first) {
/* Remove it from the string */
str = setCharAt(str,i,'');
}
}
curr_index++;
}
return str;
}
function setCharAt(str,index,chr) {
if(index > str.length-1) return str;
return str.substr(0,index) + chr + str.substr(index+1);
}
Here's what I used - haven't tested it for spaces or special characters, but should work fine for pure strings:
function uniquereduce(instring){
outstring = ''
instringarray = instring.split('')
used = {}
for (var i = 0; i < instringarray.length; i++) {
if(!used[instringarray[i]]){
used[instringarray[i]] = true
outstring += instringarray[i]
}
}
return outstring
}
Just came across a similar issue (finding the duplicates). Essentially, use a hash to keep track of the character occurrence counts, and build a new string with the "one-hit wonders":
function oneHitWonders(input) {
var a = input.split('');
var l = a.length;
var i = 0;
var h = {};
var r = "";
while (i < l) {
h[a[i]] = (h[a[i]] || 0) + 1;
i += 1;
}
for (var c in h) {
if (h[c] === 1) {
r += c;
}
}
return r;
}
Usage:
var a = "anaconda";
var b = oneHitWonders(a); // b === "cod"
Try this code, it works :)
var str="anaconda";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 && str.lastIndexOf(obj,i-1)==-1){
return obj;
}
}
).join("");
//output: "cod"
This should work using Regex ;
NOTE: Actually, i dont know how this regex works ,but i knew its 'shorthand' ,
so,i would have Explain to you better about meaning of this /(.+)(?=.*?\1)/g;.
this regex only return to me the duplicated character in an array ,so i looped through it to got the length of the repeated characters .but this does not work for a special characters like "#" "_" "-", but its give you expected result ; including those special characters if any
function removeDuplicates(str){
var REPEATED_CHARS_REGEX = /(.+)(?=.*?\1)/g;
var res = str.match(REPEATED_CHARS_REGEX);
var word = res.slice(0,1);
var raw = res.slice(1);
var together = new String (word+raw);
var fer = together.toString();
var length = fer.length;
// my sorted duplicate;
var result = '';
for(var i = 0; i < str.length; i++) {
if(result.indexOf(str[i]) < 0) {
result += str[i];
}
}
return {uniques: result,duplicates: length};
} removeDuplicates('anaconda')
The regular expression /([a-zA-Z])\1+$/ is looking for:
([a-zA-Z]]) - A letter which it captures in the first group; then
\1+ - immediately following it one or more copies of that letter; then
$ - the end of the string.
Changing it to /([a-zA-Z]).*?\1/ instead searches for:
([a-zA-Z]) - A letter which it captures in the first group; then
.*? - zero or more characters (the ? denotes as few as possible); until
\1 - it finds a repeat of the first matched character.
I have 3 loopless, one-line approaches to this.
Approach 1 - removes duplicates, and preserves original character order:
var str = "anaconda";
var newstr = str.replace(new RegExp("[^"+str.split("").sort().join("").replace(/(.)\1+/g, "").replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")+"]","g"),"");
//cod
Approach 2 - removes duplicates but does NOT preserve character order, but may be faster than Approach 1 because it uses less Regular Expressions:
var str = "anaconda";
var newstr = str.split("").sort().join("").replace(/(.)\1+/g, "");
//cdo
Approach 3 - removes duplicates, but keeps the unique values (also does not preserve character order):
var str = "anaconda";
var newstr = str.split("").sort().join("").replace(/(.)(?=.*\1)/g, "");
//acdno
function removeduplicate(str) {
let map = new Map();
// n
for (let i = 0; i < str.length; i++) {
if (map.has(str[i])) {
map.set(str[i], map.get(str[i]) + 1);
} else {
map.set(str[i], 1);
}
}
let res = '';
for (let i = 0; i < str.length; i++) {
if (map.get(str[i]) === 1) {
res += str[i];
}
}
// o (2n) - > O(n)
// space o(n)
return res;
}
If you want your function to just return you a unique set of characters in your argument, this piece of code might come in handy.
Here, you can also check for non-unique values which are being recorded in 'nonUnique' titled array:
function remDups(str){
if(!str.length)
return '';
var obj = {};
var unique = [];
var notUnique = [];
for(var i = 0; i < str.length; i++){
obj[str[i]] = (obj[str[i]] || 0) + 1;
}
Object.keys(obj).filter(function(el,ind){
if(obj[el] === 1){
unique+=el;
}
else if(obj[el] > 1){
notUnique+=el;
}
});
return unique;
}
console.log(remDups('anaconda')); //prints 'cod'
If you want to return the set of characters with their just one-time occurrences in the passed string, following piece of code might come in handy:
function remDups(str){
if(!str.length)
return '';
var s = str.split('');
var obj = {};
for(var i = 0; i < s.length; i++){
obj[s[i]] = (obj[s[i]] || 0) + 1;
}
return Object.keys(obj).join('');
}
console.log(remDups('anaconda')); //prints 'ancod'
function removeDuplicates(str) {
var result = "";
var freq = {};
for(i=0;i<str.length;i++){
let char = str[i];
if(freq[char]) {
freq[char]++;
} else {
freq[char] =1
result +=char;
}
}
return result;
}
console.log(("anaconda").split('').sort().join('').replace(/(.)\1+/g, ""));
By this, you can do it in one line.
output: 'cdo'
function removeDuplicates(string){
return string.split('').filter((item, pos, self)=> self.indexOf(item) == pos).join('');
}
the filter will remove all characters has seen before using the index of item and position of the current element
Method 1 : one Simple way with just includes JS- function
var data = 'sssssddddddddddfffffff';
var ary = [];
var item = '';
for (const index in data) {
if (!ary.includes(data[index])) {
ary[index] = data[index];
item += data[index];
}
}
console.log(item);
Method 2 : Yes we can make this possible without using JavaScript function :
var name = 'sssssddddddddddfffffff';
let i = 0;
let newarry = [];
for (let singlestr of name) {
newarry[i] = singlestr;
i++;
}
// now we have new Array and length of string
length = i;
function getLocation(recArray, item, arrayLength) {
firstLaction = -1;
for (let i = 0; i < arrayLength; i++) {
if (recArray[i] === item) {
firstLaction = i;
break;
}
}
return firstLaction;
}
let finalString = '';
for (let b = 0; b < length; b++) {
const result = getLocation(newarry, newarry[b], length);
if (result === b) {
finalString += newarry[b];
}
}
console.log(finalString); // sdf
// Try this way
const str = 'anaconda';
const printUniqueChar = str => {
const strArr = str.split("");
const uniqueArray = strArr.filter(el => {
return strArr.indexOf(el) === strArr.lastIndexOf(el);
});
return uniqueArray.join("");
};
console.log(printUniqueChar(str)); // output-> cod
function RemDuplchar(str)
{
var index={},uniq='',i=0;
while(i<str.length)
{
if (!index[str[i]])
{
index[str[i]]=true;
uniq=uniq+str[i];
}
i++;
}
return uniq;
}
We can remove the duplicate or similar elements in string using for loop and extracting string methods like slice, substring, substr
Example if you want to remove duplicate elements such as aababbafabbb:
var data = document.getElementById("id").value
for(var i = 0; i < data.length; i++)
{
for(var j = i + 1; j < data.length; j++)
{
if(data.charAt(i)==data.charAt(j))
{
data = data.substring(0, j) + data.substring(j + 1);
j = j - 1;
console.log(data);
}
}
}
Please let me know if you want some additional information.

Categories