I want to do a variation of the get Maximum subarray from leetcode in which I collect the entire maximum subarray as well, but I can't seem to figure out what I'm missing.
var maxSubArray = function(nums) {
let currSum = 0;
let maxSum = -Infinity;
let currArray = [];
let maxArray = [];
for (let i = 0; i < nums.length; i++) {
currSum += nums[i];
if (Math.max(currSum, maxSum) != maxSum) {
maxArray = currArray;
maxSum = currSum;
currArray.push(nums[i]);
}
maxSum = Math.max(currSum, maxSum);
if (currSum < 0) {
currSum = 0;
currArray = []
}
}
console.log(maxArray);
return maxSum;
};
I recognize why this is wrong, as the currSum value cannot have a negative component because it'd always be a lower sum than the current maxSum. But I'm not sure what condition it would require for this. I feel like I'm missing something obvious but cannot think of it :(
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
I was going about it the wrong way as I was storing an array when I could have just stored the index.
var maxSubArray = function(nums) {
let currSum = 0;
let maxSum = -Infinity;
let prevMax = -Infinity;
let start = 0;
let end = 0;
for (let i = 0; i < nums.length; i++) {
currSum += nums[i];
if (nums[i] > maxSum) {
start = i;
}
if (Math.max(currSum, maxSum) != maxSum) {
maxSum = currSum;
end = i;
}
if (currSum < 0) {
currSum = 0;
if (nums[i+1] != undefined) {
start = i+1;
}
}
}
console.log(start, end);
console.log(nums.slice(start, end+1))
return maxSum;
};
Related
Well in this question I have to find the longest sequence of zeros in the binary representation of an integer.
After a lot of hard work, I'm able to find the longest sequence of zeros with my logic which I changed many times.
I have one problem with my logic which is if I input an integer that has no gap in it has to give me an answer 0 which I tried to make by myself but I failed.
Right now if I input an integer that has no gap it gives me output infinity.
I want my answer to print 0 when the binary representation of an integer has no gap in it.
var dn = prompt("Enter a number: ");
var bn = new Array();
var i = 0;
var binary = [];
while (dn != 0) {
bn[i] = dn % 2;
dn = Math.floor(dn / 2);
i++;
}
for (var j = i - 1; j >= 0; j--) {
binary.push(bn[j]);
}
console.log(binary.join(""));
var currentGap = 0;
var gaps = [];
var len = binary.length;
for (var k = 0; k < len; k++) {
if (binary[k] == 0) {
currentGap++;
if (binary[k + 1] == 1) {
gaps.push(currentGap);
currentGap = 0;
}
}
}
console.log(Math.max(...gaps));
You could add initialize gaps with 0, or add condition when gaps remains empty to print 0 else max of gaps.
var dn = prompt("Enter a number: ");
var bn = new Array();
var i = 0;
var binary = [];
while (dn != 0) {
bn[i] = dn % 2;
dn = Math.floor(dn / 2);
i++;
}
for (var j = i - 1; j >= 0; j--) {
binary.push(bn[j]);
}
console.log(binary.join(""));
var currentGap = 0;
//var gaps = []
var gaps = [0];
var len = binary.length;
for (var k = 0; k < len; k++) {
if (binary[k] == 0) {
currentGap++;
if (binary[k + 1] == 1) {
gaps.push(currentGap);
currentGap = 0;
}
}
}
//if (gaps.length === 0)
// console.log(0)
//else
// console.log(Math.max(...gaps));
console.log(Math.max(...gaps));
You can simply print 0 if your gaps array has no length.
var dn = prompt("Enter a number: ");
var bn = new Array();
var i = 0;
var binary = [];
while (dn != 0) {
bn[i] = dn % 2;
dn = Math.floor(dn / 2);
i++;
}
for (var j = i - 1; j >= 0; j--) {
binary.push(bn[j]);
}
console.log(binary.join(""));
var currentGap = 0;
var gaps = [];
var len = binary.length;
for (var k = 0; k < len; k++) {
if (binary[k] == 0) {
currentGap++;
if (binary[k + 1] == 1) {
gaps.push(currentGap);
currentGap = 0;
}
}
}
console.log(gaps.length ? Math.max(...gaps) : 0); // <-- This
I apologize if I'm misunderstanding your question, but would this satisfy your problem?
const s = prompt("Enter a number:");
const longest = Math.max(...parseInt(s).toString(2).split('1').map(s=>s.length));
console.log(longest);
just change var gaps = [];
to var gaps = [0];
You can also do that...
let dn = parseInt(prompt("Enter a number: "))
if (isNaN(dn)) console.log('Not a Number!')
else
{
let
dnStr = dn.toString(2) // binary convertion
, count = 0
, zVal = '0'
;
while (dnStr.includes(zVal) )
{
count++
zVal += '0'
}
console.log( `${dnStr}\n--> ${count}` )
}
If you want to do your own binary convertion, prefert o use Javasscript binary opérators:
let dn = parseInt(prompt("Enter a number: "))
if (isNaN(dn)) console.log('Not a Number!')
else
{
let gap = [0]
let Bin = []
let count = 0
for (;;)
{
Bin.unshift( dn & 1 ) // --> dn % 2
if (dn & 1)
{
gap.push(count)
count = 0
}
else count++
dn >>>=1 // --> dn = Math.floor(dn / 2)
if (!dn) break // --> if (dn === 0 )
}
console.log(Bin.join(''))
console.log(Math.max(...gap))
}
I had a go at this and this is what I came up with as a function:
function binaryGap(N){
let binary = Math.abs(N).toString(2); // Convert to Binary string
let binarySplit = binary.split("1"); // Split the string wherever there is "1"
let tempBinaryArr = []; // create an empty array to store the element from Splice
let max = 0; // Setting the max length to zero to compare with each element
// Removing the zeros at the end
if(binarySplit[binarySplit.length -1] == 0){
tempBinaryArr = binarySplit.splice(binarySplit.length -1, 1);
}
//Looping through each element of binarySplit to compare with variable max
for(let j=0; j < binarySplit.length; j++){
if(max < binarySplit[j].length){
max = binarySplit[j].length;
}
}
return `Longest Sequence of Zeros: ${max}`;
}
If I understood the task correctly, you can arrange the logic in something like this. In case if the input comes as a string you don't need the .toString() part
function splitByZero(str) {
const eachSubstr = str
.toString()
.split(1)
.filter((e) => e); //to remove empty values in the new array
let maxLength = 0;
for (const substr of eachSubstr) {
if (maxLength < substr.length) {
maxLength = substr.length;
}
}
console.log(maxLength);
}
splitByZero(111011100011);
function findLongestDistance(){
findGap("1000100100001");
findGap("1000100");
findGap("000100");
findGap("10000");
findGap("000001");
findGap("111111")
}
function findGap(n){
var split = n.split(/1/g);
var longestZeros = 0;
if(split.length>2){
for(var i in split){
var len = split[i].length;
if(len>longestZeros){
longestZeros = len;
}
}
console.log(longestZeros);
return longestZeros;
}
console.log(0);
return 0;
}
I am currently doing a codewars problem, and I think I almost got it however, I ran across a problem when sorting index values with the same letter. link to problem is here. https://www.codewars.com/kata/5782dd86202c0e43410001f6
function doMath(s) {
let strSplit = s.split(' ');
let clonedArr = strSplit.slice();
for (let i = 0; i < strSplit.length; i++) {
for (let j = 0; j < strSplit[i].length; j++) {
let current = strSplit[i][j];
if (isNaN(current)) {
let letter = current;
strSplit[i] = strSplit[i].replace(letter, '');
strSplit[i] = letter + strSplit[i];
}
}
}
let sortedArr = strSplit.sort();
console.log(sortedArr);
// ["b900", "y369", "z123", "z246", "z89"]
let noLetterArr = sortedArr.map(x => {
return x.slice(1);
});
let numberArr = noLetterArr.map(y => {
return +y;
})
let firstEl = numberArr[0];
for (let i = 1; i < numberArr.length; i++) {
if (numberArr.indexOf(numberArr[i]) % 4 == 1) {
firstEl += numberArr[i];
}
if (numberArr.indexOf(numberArr[i]) % 4 == 2) {
firstEl -= numberArr[i];
}
if (numberArr.indexOf(numberArr[i]) % 4 == 3) {
firstEl *= numberArr[i];
}
}
return firstEl;
}
console.log(doMath('24z6 1z23 y369 89z 900b'));
I would like to sort the sortedArr the ones with the same letter by how they first appeared in string. So since "z246" appeared first in the original string. I would like to have that before "1z23". I had a hard time creating a function for that.
var al = [];
function doMath(s) {
var ar = s.split(" ");
for (let i = 0; i < ar.length; i++) {
for (let char of ar[i]) {
let temp = char.match(/[a-z]/i);
if (temp) {
al[i] = char;
ar[i] = ar[i].replace(char, '');
ar[i] = char + ar[i];
}
}
}
al = al.sort();
//New Sort Logic to pass above test case and others too
var n = [];
for (let i = 0; i < al.length; i++) {
for (let j = 0; j < ar.length; j++) {
if (ar[j].startsWith(al[i]) && !n.includes(ar[j])) {
n.push(ar[j]);
}
}
}
var result = parseInt(n[0].substr(1)),
count = 1;
for (let i = 1; i < n.length; i++) {
if (count == 1) {
result = result + parseInt(n[i].substr(1));
count++;
} else if (count == 2) {
result = result - parseInt(n[i].substr(1));
count++;
} else if (count == 3) {
result = result * parseInt(n[i].substr(1));
count++;
} else if (count == 4) {
result = result / parseInt(n[i].substr(1));
count = 1;
}
}
return Math.round(result);
}
I am trying to do one problem of hackerrank but I am not able to solve that problem
Can someone please help me with wrong logic implementation done by me?
problem
Print the length of the longest string, such that is a child of both s1 and s2.
Sample Input
HARRY
SALLY
Sample Output
2
Explanation
The longest string that can be formed by deleting zero or more characters from HARRY and SALLY is AY, whose length is 2.
Sample Input 1
AA
BB
Sample Output 1
0
Explanation 1
AA and BB have no characters in common and hence the output is 0
Sample Input 2
SHINCHAN
NOHARAAA
Sample Output 2
3
Explanation 2
The longest string that can be formed between SHINCHAN and NOHARAAA while maintaining the order is NHA.
I have written some logic which is as follows:
function commonChild(s1, s2) {
var arr = s2.split(),
currenString = '',
maxLength = 0,
index = -1;
console.log(arr);
for (var i = 0; i < s1.length; i++) {
var char = s1.charAt(i),
charIndex = arr.indexOf(char);
console.log(char)
if (index < charIndex) {
index = charIndex;
currenString +=char;
}
maxLength= Math.max(maxLength,currenString.length)
}
return maxLength;
}
commonChild('ABCDEF', 'FBDAMN');
console.log(commonChild('ABCDEF', 'FBDAMN'));
pardon me. this is an unoptimized solution.
function maxCommon(a, b, offset) {
offset = offset || 0;
if (a === b) {
return [[a, b]];
}
var possibleSolns = [];
for (var i = 0 + offset; i < a.length; i++) {
for (var j = 0 + offset; j < b.length; j++) {
if (a.charAt(i) === b.charAt(j)) {
possibleSolns.push([
a.substring(0, offset) + a.substring(i),
b.substring(0, offset) +b.substring(j)
]);
break;
}
}
}
var results = [];
possibleSolns.forEach(function(soln) {
var s = maxCommon(soln[0], soln[1], offset+1);
if (s.length === 0) {
s = [[soln[0].substring(0, offset +1), soln[1].substring(0, offset +1)]];
}
results = results.concat(s);
});
return results;
}
var maxLen = -1;
var soln = null;
maxCommon("ABCDEF", "FBDAMN").map(function(_) {
return _[0];
}).forEach(function(_) {
if (_.length > maxLen) {
soln = _;
maxLen = _.length;
}
});
console.log(soln);
I kept most of your logic in the answer:
function commonChild(s1, s2) {
var // Sets strings to arrays
arrayString1 = s1.split(""),
arrayString2 = s2.split(""),
collectedChars = "",
maxLength = 0,
max = arrayString1.length;
for (var i = 0; i < max; i++) {
var
char = arrayString1[i],
count = arrayString2.indexOf(char);
// check if char is in second string and not in collected
if (count != -1 && collectedChars.indexOf(char) == -1) {
collectedChars += char;
maxLength++;
}
}
return maxLength;
}
// expected output 4
console.log(commonChild(
'ABCDEF',
'FBDAMN'
));
// expected output 1
console.log(commonChild(
'AA',
'FBDAMN'
));
Using lodash and spread operation you can do it in this way.
const test = (first, second) => {
const stringArray1 = [...first];
const stringArray2 = [...second];
return _.intersection(stringArray1, stringArray2).length;
}
console.log(test('ABCDEF', 'FBDAMN'));
You can solve it using lcs least common subsequence
function LCS(s1,s2,x,y){
var result = 0;
if(x==0 || y==0){
result = 0
}else if(s1[x-1] == s2[y-1]){
result = 1+ LCS(s1,s2,x-1,y-1)
} else if(s1[x-1] != s2[y-1]){
result = Math.max(LCS(s1,s2,x-1,y), LCS(s1,s2,x,y-1))
}
return result;
}
// Complete the commonChild function below.
function commonChild(s1, s2) {
return LCS(s1,s2,s1.length,s2.length);
}
Based on your code before the edit.
One little change is to change var arr = s2.split() to split('').
The main change in the logic is that I added a loop to run over the string each time from another character (first loop from the first, second from the second etc).
function commonChild(s1, s2) {
var arr = s2.split(''),
currenString = '',
maxLength = 0,
index = -1,
j = -1;
for (var ii = 0; ii < s1.length; ii++) {
index = -1;
currenString = '';
for (var i = ii; i < s1.length; i++) {
var char = s1.charAt(i),
j = arr.indexOf(char);
if (index < j) {
index = j;
currenString += char;
}
maxLength = Math.max(maxLength, currenString.length)
}
}
return maxLength;
}
console.log(commonChild('ABCDEF', 'FBDAMN'));
This function is supposed to comb through an array and find the largest product of any two adjacent indices (I.E the answer to [4,5,2,1] would be 20.) Most of my tests seem to work, but when inputArray = [-23, 4, -3, 8, -12] , my output is 0. Why?
function largestProduct(inputArray) {
let arr = inputArray;
let answer = 0;
let ansArr = [];
for(let i = 0; i < arr.length - 1;i++){
let product = arr[i] * arr[i+1];
ansArr.push(product);
}
for(let i = 0; i < ansArr.length; i++){
if(ansArr[i] > answer){
answer = ansArr[i];
}
}
return answer
}
All the products are less than 0. You should init answer with -Infinity, which will always be less than your product.
function largestProduct(inputArray) {
let arr = inputArray;
let answer = -Infinity;
let ansArr = [];
for (let i = 0; i < arr.length - 1; i++) {
let product = arr[i] * arr[i + 1];
ansArr.push(product);
}
for (let i = 0; i < ansArr.length; i++) {
if (ansArr[i] > answer) {
answer = ansArr[i];
}
}
return answer
}
console.log(largestProduct([-23, 4, -3, 8, -12]));
You can also refactor your code to a single loop:
function largestProduct(arr) {
let answer = -Infinity;
for (let i = 0; i < arr.length - 1; i++) {
const product = arr[i] * arr[i + 1];
answer = answer > product ? answer : product;
}
return answer
}
console.log(largestProduct([-23, 4, -3, 8, -12]));
The case when your all the products are less than 0. You should init answer equal 0 after the first loop, so I was Thinking in this solution
function largestProduct(inputArray) {
let arr = inputArray;
let ansArr = [];
for(let i = 0; i < arr.length - 1;i++){
let product = arr[i] * arr[i+1];
ansArr.push(product);
}
let answer = ansArr.length > 0 ? ansArr[1] : 0;
for(let i = 0; i < ansArr.length; i++){
if(ansArr[i] > answer){
answer = ansArr[i];
}
}
return answer
}
I have written a function and called another function inside but my tests show that it is not time optimized. How can I make the following code faster?
function maxSum(arr, range) {
function sumAll(array1, myrange) {
var total = 0;
if (Array.isArray(myrange)) {
for (var i = myrange[0]; i <= myrange[1]; i++) {
total += array1[i];
}
return total;
} else return array1[myrange];
}
var mylist = [];
var l = range.length;
for (var n = 0; n < l; n++) {
mylist.push(sumAll(arr, range[n]));
}
return Math.max.apply(null, mylist);
}
Algorithmic optimization: create new array with cumulative sums from index 0 to every index
cumsum[0] = 0;
for (var i = 1; i <= arr.Length; i++) {
cumsum[i] = cumsum[i-1] + arr[i-1]
Now you don't need to calculate sums for every range - just get difference
sum for range (i..j) = cumsum[j+1] - cumsum[i];
in your terms:
function sumAll(array1, myrange) {
return cumsum[myrange[1]+1] - cumsum[myrange[0]];
}
example:
arr = [1,2,3,4]
cumsum = [0,1,3,6,10]
sum for range 1..2 = 6 - 1 = 5
P.S. If your array might be updated, consider Fenwick tree data structure
1) You can define the function sumAll outside of the function maxSum because every time you call maxSum the javascript engine is recreating a fresh new function sumAll.
2) You can define myrange[1] as a variable in the initialiser part to avoid javascript to look for myrange[1] at each iteration.
for (var i = myrange[0]; i <= myrange[1]; i++) {
total += array1[i];
}
become this:
for (var i = myrange[0], len = myrange[1]; i <= len; i++) {
total += array1[i];
}
Full working code based on #MBo's excellent optimization. This passes all the tests at https://www.codewars.com/kata/the-maximum-sum-value-of-ranges-challenge-version/train/javascript, which I gather is where this problem comes from.
function maxSum(arr, ranges) {
var max = null;
var sums = [];
var sofar = 0;
for (var i = 0; i <= arr.length; i++) {
sums[i] = sofar;
sofar += arr[i];
}
for (var i = 0; i < ranges.length; i++) {
var sum = sums[ranges[i][1]+1] - sums[ranges[i][0]];
if (max === null || sum > max) {
max = sum;
}
}
return max;
}