Given a string, find the first non-repeating character in it and return its index. If it doesn't exist, return -1.
leetcode question
"cc" // -1
"ccdd" // -1
"leetcode" // 1
"loveleetcode" // 2
"abcabd" // 2
"thedailybyte" // 1
"developer" // 0
My approach passed all the test cases except the 2nd test case "ccdd". I am expecting -1 but receiving 4. Not sure why.
var firstUniqChar = function(s) {
if(!s || s.length === 0 ) return -1
else if(s.length === 1) return 0
let pointer1 = 0
let pointer2 = pointer1 + 1
if(s.length > 2){
while(pointer2 <= s.length - 1){
if(s[pointer1] !== s[pointer2])
pointer2++
else if(s[pointer1] === s[pointer2])
pointer1++
}
return pointer1
}
return -1
};
this is too old, but still can be too much shorter:
const firstUniqChar = (_str) => {
for (let i= 0; i < _str.length; i+= 1) {
if (_str.indexOf(_str[i]) === _str.lastIndexOf(_str[i])) return i+1;
}
return -1;
}
can you help me to write a function in javascript to Given two strings, find if they are one edit away from each other example :
(pale, ple ) true
(pales, pale ) true
(pale, bale ) true
(pale, bake) false
(face, facts ) false
Can you try this function to check that string only differs by one edit.
function checkDifferntString(str1, str2) {
let diff = 0;
if (str1 === str2) return true; // equal return true
let lengthDiff = Math.abs(str1.length - str2.length)
if (lengthDiff > 1) return false; // checks length diff if > 2 return false
for (let i=0; (i<str1.length || i < str2.length);i++) {
if (diff > 1) return false; // diff greater than 1 return false
if (str1.charAt(i) !== str2.charAt(i)) diff++
}
if (diff <= 1) return true
else return false;
}
console.log(checkDifferntString("pale", "pale")) // true
console.log(checkDifferntString("pale", "pales")) // true
console.log(checkDifferntString("pales", "pale")) // true
console.log(checkDifferntString("pales", "bale")) // false
I hope it helps. Thanks!
Check this out.
I made a simple function that iterates through the given two strings and check if there's more than 1 difference (in terms of characters) between these strings, an optional argument cs to allow case sensitivity, by default it equals to false, so 'a' and 'A' are the same.
function isEditFrom(str1, str2, cs) {
var cs = cs || false, i = 0, diff = 2, len1 = str1.length, len2 = str2.length, l = (len1 > len2) ? len1: len2;
if(len1 !== 0 && len2 !== 0) {
if(cs === false) {
str1 = str1.toLowerCase();
str2 = str2.toLowerCase();
}
for(; i < l; i++) {
if(str1[i] !== str2[i]) {
if(--diff === 0) {
return false;
}
}
}
return true;
} else {
return false;
}
}
and now we call that function:
isEditFrom('Pale', 'bAle'); // returns True
isEditFrom('Pale', 'bAle', true); // returns False as we set the third argument to true enabling case sensitivity, 'a' != 'A'
isEditFrom('face', 'facts'); // returns False
There are multiple solutions to how to check if parentheses are balanced, but I haven't found a single one that would be checking both for balanced quotes and parentheses.
I have been unsuccessfully trying to adapt this solution (codereview - balanced parentheses) to be able to check if the quotes and parentheses are balanced.
For example this should be unbalanced ("back-to-school)"
Original code:
function parenthesesAreBalanced(string) {
var parentheses = "[]{}()",
stack = [],
i, character, bracePosition;
for(i = 0; character = string[i]; i++) {
bracePosition = parentheses.indexOf(character);
if(bracePosition === -1) {
continue;
}
if(bracePosition % 2 === 0) {
stack.push(bracePosition + 1); // push next expected brace position
} else {
if(stack.length === 0 || stack.pop() !== bracePosition) {
return false;
}
}
}
return stack.length === 0;
}
My code - mostly similar - but added an unbalanced quotes check.
function areQuotesAndParenthesesBalanced(s: string): boolean {
const parens = '[]{}()',
parensStack = [];
let index, char, numOfQuotes = 0;
for (index = 0; char = s[index++];){
const bracePosition = parens.indexOf(char);
let braceType;
if (bracePosition === -1 && char !== '"')
continue;
braceType = bracePosition % 2 ? 'closed' : 'open';
//check for double quotes mixed with parentheses
if(char === '"'){
const lastInStack = parensStack[parensStack.length - 1];
numOfQuotes++;
if(lastInStack === '"'){
numOfQuotes--;
parensStack.pop();
}else if(numOfQuotes > 0 && lastInStack !== '"'){
return false;
}else{
parensStack.push('"');
}
}
if (braceType === 'closed') {
if (!parensStack.length || parens.indexOf(parensStack.pop()) != bracePosition - 1)
return false;
} else {
parensStack.push(char);
}
}
//If anything is left on the stack <- not balanced
return !parensStack.length;
}
It is quite tricky for me to determine what's the best approach. With parentheses, you always know when one is open or closed, with quotes, not so much.
function tokensAreBalanced(string) {
var asymmetricTokens = "[]{}()",
symmetricTokens = '"',
stack = [],
i, character, tokenPosition;
for(i = 0; character = string[i]; i++) {
tokenPosition = asymmetricTokens.indexOf(character);
if(tokenPosition >= 0) {
if(tokenPosition % 2 === 0) {
stack.push(asymmetricTokens[tokenPosition + 1]); // push next expected token
} else if(stack.length === 0 || stack.pop() !== character) {
return false;
}
} else {
if(symmetricTokens.includes(character)) {
if(stack.length > 0 && stack[stack.length - 1] === character) {
stack.pop();
} else {
stack.push(character);
}
}
}
}
return stack.length === 0;
}
console.log('("back-to-school)"', tokensAreBalanced('("back-to-school)"'));
console.log('("back-to-school)', tokensAreBalanced('("back-to-school)'));
console.log('("back-to-school")', tokensAreBalanced('("back-to-school")'));
console.log('(ele AND car) OR ("ele car)")', tokensAreBalanced('(ele AND car) OR ("ele car)")'));
This performs a check for push() or pop() of " in 2 ways.
If stack is empty or last character in stack does not equal ", then insert this " into stack.
If stack is not empty and last character in stack is equal to ", then pop() the " in stack itself. This is done because I do a form of greedy matching here since a " for already stack " means expression inside "..." was evaluated. So, we are safe to match these 2 " and proceed with the next.
Works well, but let me know if it fails for any case.
function areQuotesAndParenthesesBalanced(s){
var pairs = {
'}':'{',
']':'[',
')':'(',
};
var stack = [];
for(var i = 0;i < s.length;++i){
switch(s.charAt(i)){
case '[': case '{':case '(':
stack.push(s.charAt(i));
break;
case ']': case '}':case ')':
if(isStackEmpty(stack) || peek(stack) !== pairs[s.charAt(i)]) return false;
stack.pop();
break;
case '"':
if(isStackEmpty(stack) || peek(stack) !== s.charAt(i)){
stack.push(s.charAt(i));
}else{
stack.pop();
}
}
}
return isStackEmpty(stack);
}
function isStackEmpty(s){
return s.length === 0;
}
function peek(s){
return s[s.length-1];
}
var tests = {
'("back-to-school")':true,
'"(back-to-school)"':true,
'("back-to-school)"':false,
'("back-to-school)':false,
'"["["["[]"]"]"]"':true,
'"["]""':false,
'"[]"""':true,
'""""':true,
'""':true,
'"':false,
'""[("")]""':true,
'""[("")]':true,
'"["["["[]"]"[""]]"]':false,
'"[]"[({})]""':true,
'"[{}"]':false
};
for(var each_test in tests){
var res = areQuotesAndParenthesesBalanced(each_test);
console.log(each_test + " --> " + (res === tests[each_test] ? "ok" : "not ok") + " , expected : " + tests[each_test]);
}
OUTPUT
("back-to-school") --> ok , expected : true
"(back-to-school)" --> ok , expected : true
("back-to-school)" --> ok , expected : false
("back-to-school) --> ok , expected : false
"["["["[]"]"]"]" --> ok , expected : true
"["]"" --> ok , expected : false
"[]""" --> ok , expected : true
"""" --> ok , expected : true
"" --> ok , expected : true
" --> ok , expected : false
""[("")]"" --> ok , expected : true
""[("")] --> ok , expected : true
"["["["[]"]"[""]]"] --> ok , expected : false
"[]"[({})]"" --> ok , expected : true
"[{}"] --> ok , expected : false
You could try putting an ordered tuple on the stack and checking based off of that.
[(,"],
[",)],
[(,"],
[",)]
== ("")("") example of a balanced stack.
[",(],
[",(],
[),"],
[),"]
== "("()")" another balanced stack
[(,"],
[),"]
== (")" trivial unbalanced stack
[(,)] <- trivial item, can ignore in implementation
[","] <- trivial item, can ignore in implementation
[",(],
[),(],
[),"]
== "()()" balanced stack
I'm too tired to actually implement this, but hopefully it gave you some ideas and illustrative examples, I'll revisit it after I get some sleep.
I would suggest simplifying the input by removing all quoted substrings. Quotes behave differently because parentheses inside quotes are not treated specially, but as normal characters. By first removing each quoted part, this "problem" is resolved from the start. Also irrelevant characters (that are not parentheses nor quotes) can be removed as well. That way we are only left with a string that has parentheses and possibly a single occurrence of a quote. The latter would immediately make the input invalid.
Here is code similar to #nice_dev's answer, with that manipulation implemented and with pairs inversed; it also deals with apostrophe as alternative delimiter:
function areQuotesAndParenthesesBalanced(s) {
const pairs = {
'{':'}',
'[':']',
'(':')',
};
const stack = [""]; // Dummy
for (const token of s.replace(/"[^"]*"|'[^']*'|[^"'{}()[\]]+/g, "")) {
if (token in pairs) {
stack.push(pairs[token]);
} else {
if (stack.at(-1) !== token) return false;
stack.pop();
}
}
return stack.length == 1; // Empty
}
// Same tests as in the answer of #nice_dev:
const tests = {
'("back-to-school")': true,
'"(back-to-school)"': true,
'("back-to-school)"': false,
'("back-to-school)': false,
'"["["["[]"]"]"]"': true,
'"["]""': false,
'"[]"""': true,
'""""': true,
'""': true,
'"': false,
'""[("")]""': true,
'""[("")]': true,
'"["["["[]"]"[""]]"]': false,
'"[]"[({})]""': true,
'"[{}"]': false
};
for (const each_test in tests){
const res = areQuotesAndParenthesesBalanced(each_test);
console.log(`${each_test} --> ${res === tests[each_test] ? "ok" : "not ok"}, expected: ${tests[each_test]}`);
}
A simple approaching way might be like this for only first braces:
function Search(str) {
const onlyBrackets = str.replace(/[a-zA-Z]/g, "");
const left = onlyBrackets.replace(/[)]/g, "");
const right = onlyBrackets.replace(/[(]/g, "");
str = left.length === right.length ? 1 : 0
return str
}
console.log(Search("(coder)(byte))")) // 0
console.log(Search("(c(oder))b(yte)")) // 1
function isParenthesisBalanced(_str) {
var parenMap = {'{':'}', '[':']', '(':')'};
var parenStack =[];
for(var i=0;i<_str.length; i++) {
if(_str[i] in parenMap) {
parenStack.push(_str[i]);
} else if(Object.values(parenMap).indexOf(_str[i]) != -1) {
if(parenMap[parenStack.pop()] != _str[i]) return false;
}
}
return true;
}
This probably has an easy solution, but I simply don't see it at the moment.
I have three if-clauses that ashould be activated based on the length of an array. The first two ones seem to work fine, but for some odd reason I can't activate the third one (arr.length === 3). Right before the if clauses I have tried an alert to test whether it gives the right length of the array and it does.
function calculateDistances() {
var arr = [];
arr.push(posM, posL, posR);
alert(arr[1])
for (var i = 0; i < arr.length; i++) {
if (!arr[i]) {
arr.splice(i,1)
}
}
alert(arr.length)
if (arr.length === 0 || 1) {
return true;
}
else if (arr.length === 2 ) {
var diameter = calculateDiameter(arr[0], arr[1])
if (diameter > minDistance) {
return false;
}
else {
return true;
}
}
else if (arr.length === 3) {
alert("hello")
var diameter1 = calculateDiameter(arr[0], arr[1]);
var diameter2 = calculateDiameter(arr[0], arr[2]);
var diameter3 = calculateDiameter(arr[1], arr[3]);
if (diameter1 && diameter2 && diameter3 < minDistance) {
return true
}
else{
return false
}
}
}
Nor can you activate the second.
There's a bug here: if (arr.length === 0 || 1) {
The 1 casts to true.
Perhaps you meant: if (arr.length === 0 || arr.length === 1) {
You need this:
if (arr.length === 0 || arr.length === 1) {
The way you put it, it is equal to
if ((arr.length === 0) || true) {
which is always true.
I think what you are looking for is below condition in the first if condition
if (arr.length === 0 || arr.length === 1) {
return true;
}
this checks whether the length of the array is 1 or it's 0. Your first if condition is always true as it has 1 which is true.
(arr.length === 0 || 1)
is always true.
You could usethis instead
if (arr.length <= 1)
{
return true;
}
I am trying to solve a JavaScript coding exercise and my code is wrong and I can't see why.
The task is:
take a string and if every letter in the string is surrounded by a '+' sign, return true, otherwise return false.
It works for most cases but doesn't work for '=a+' for example and I don't understand why. Could someone explain?
function SimpleSymbols(str) {
for (var i = 0; i < str.length; i++) {
if (str[0].match(/[a-z]/i) || str[str.length - 1].match(/[a-z]/i)) {
return false;
} else {
if (str[i].match(/[a-z]/i) && (str[i - 1] !== "+" || str[i + 1] !== "+")) {
return false;
} else {
return true;
}
}
}
}
SimpleSymbols(readline());
The issue is the inner else clause. It should be elimninated, and instead, the function should return true after the for block.
function SimpleSymbols(str) {
for (var i = 0; i < str.length; i++) {
if (str[0].match(/[a-z]/i) || str[str.length - 1].match(/[a-z]/i)) {
return false;
} else {
if (str[i].match(/[a-z]/i) && (str[i - 1] !== "+" || str[i + 1] !== "+")) {
return false;
}
}
}
return true;
}
Could you match against this and return the result:
^\+(?:[a-z]\+)*$
https://regex101.com/r/1zXUJD/1
looks for strings that start with a '+' and then any number of [a-z]+ after that until the end of the string.