Related
I'm working on this CodeSignal exercise that says:
You have an array of integers nums and an array queries, where queries[i] is a pair of indices (0-based). Find the sum of the elements in nums from the indices at queries[i][0] to queries[i][1] (inclusive) for each query, then add all of the sums for all the queries together. Return that number modulo 10^9 + 7.
This is my code:
function solution(nums, queries) {
let accumulator = 0;
let M = 1000000007;
for(let i = 0; i < queries.length; i++){
accumulator += nums.slice(queries[i][0],queries[i][1]+1).reduce((a,b) => a+b);
}
return accumulator < 0 ? ((accumulator % M) + M) % M : accumulator%M;
}
It works perfectly, BUT the penultimate hidden test throws a timeout, and I'm out of ideas on how to make this faster.
Thanks in advance for any help you may provide.
PS: if you're wondering about the difference using modulo at the end, it's because it seems JS has a bug when using negative numbers.
As tflave pointed out, using a prefix sum made the code perform faster, and it didn't timeout. Here's the code if anyone needs it:
let pre = new Array(1000,0);
function preCompute(nums)
{
let n = nums.length;
pre[0] = nums[0];
for (let i = 1; i < n; i++) {
pre[i] = nums[i] + pre[i - 1];
}
}
function solution(nums, queries)
{
preCompute(nums);
let accumulator = 0;
let M = 1000000007;
for(let i = 0; i < queries.length; i++){
if (queries[i][0] === 0) {
accumulator += pre[queries[i][1]];
} else {
accumulator += pre[queries[i][1]] - pre[queries[i][0] - 1];
}
}
return accumulator < 0 ? ((accumulator % M) + M) % M : accumulator%M;
}
What i need to do - simple task - I am looping the array. When array[i] === 0;
i want to +1 to start, it will be the same for array[i] === 1.
But when array[i] will go back (be back where it was a moment ago) i don't want to +1 to start, and i did that code :
var start = 0;
var array = [0,1,0,0,1,0,0,1];
for (i=0; i < array.length; i ++) {
if (array[i] === 0) {
start += 1;
if (array[i + 1] === 1) {
start -= 1;
}
}
else if (array[i] === 1) {
start += 1;
if (array[i + 1] === 0) {
start -= 1;
}
}
}
console.log(start)
But what if array = [0,1,1,1,0,0,0,1,0,0,0,1]; , if array[i] will go back where it was a long time ago? I dont want then +1 to start.
Imagine 0 and 1 like -1 and +1 on chart, so console.log(start) from array = [0,1,1,1,0,0,0,1,0,0,0,1] should be 5.
My code is some kind of hard coding, have you any ideas how to fix that?
Thanks for answers in advance!
Example from comments
[0,1,1,1,0,0,0,1,0,0,0,1] should produce a result of 5; you need to imagine 0 == -1 and 1 == +1.
Then the array looks like [-1,+1,+1,+1,-1,-1,-1,+1,-1,-1,-1,+1] and begins this from 0 we have 5 positions where i was only 1 time.
As it looks like, you need to count the changes of the values in the array. You need to store the last value for checking the next value. If the last value and the actual value is different, you got a change and need to count.
function getChanges(array) {
var count = 0,
last = array[0],
i;
for (i = 1; i < array.length; i++) {
if (last !== array[i]) {
count++;
last = array[i];
}
}
return count;
}
console.log(getChanges([0, 1, 0, 0, 1, 0, 0, 1]));
console.log(getChanges([0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1]));
As #nurdyguy has pointed out, your call for array[i+1] will be out of bounds for the last element. I have flipped the comparison to the previous element and started the loop on the second element to counter this.
You seem to be calculating +=1 regardless of the binary result then only -=1 when the next element in the array differs so essentially i think you have the opposite of what you are looking for :
var start = 0;
var array = [0,1,0,0,1,0,0,1];
for (i=1; i < array.length; i++) {
if (array[i] === array[i-1]) {
start++;
}
}
Now if you want to calculate the times the element changes from each step then you can just flip the logical:
var start = 0;
var array = [0,1,0,0,1,0,0,1];
for (i=1; i < array.length; i++) {
if (array[i] !== array[i-1]) {
start++;
}
}
console.log("The result is: " + start) // The result is: 5
I think this is what you are after, please elaborate if not.
Edit:
Apologies, I did test your other array and the result was also 5.
What you are looking for is this then:
var start = 0;
var array = [0,1,1,1,0,0,0,1,0,0,0,1];
for (i=0; i < array.length; i++) {
start += array[i];
}
console.log("The result is: " + start) // The result is: 5
If the array of 0 and 1 is only as an example then use a logical:
var start = 0;
var array = [0,1,1,1,0,0,0,1,0,0,0,1];
for (i=0; i < array.length; i++) {
array[i] == 1 ? ++start : +-start;
}
console.log("The result is: " + start) // The result is: 5
or:
var start = 0;
var array = [0,1,1,1,0,0,0,1,0,0,0,1];
for (i=0; i < array.length; i++) {
if (array[i] == 1) {
++start
}
}
console.log("The result is: " + start) // The result is: 5
If the array becomes [-1,1,1,1,-1,-1,-1,1,-1,-1,-1,1] like you said then the result is not 5, it's -3?
Guys i'm trying to write an algorithm where I pass in a large string and let it loop through the string and whatever palindrome it finds, it pushes into array but for some reason my browser is crashing once i put in the while loop and I have no
function arrOfPalindromes(str) {
var palindromeArrays = []
var plength = palindromeArrays.length
// grab first character
// put that in a temp
// continue and look for match
// when match found go up one from temp and down one from index of loop
// if matched continue
// else escape and carry on
// if palendrome push into array
var counter = 0;
for (var i = 0; i < str.length; i++) {
for (var j = 1; j < str.length - 1; j++) {
if (str[i + counter] === str[j - counter]) {
while (str[i + counter] === str[j - counter]) {
console.log(str[j], str[i])
// append the letter to the last index of the array
palindromeArrays[plength] += str[i]
counter++
}
}
}
}
return palindromeArrays
}
var result2 = arrOfPalindromes('asdfmadamasdfbigccbigsdf')
console.log(result2)
Do not mention about the algorithm but the condition
while (str[i + counter] === str[j - counter])
Make your code crash. A little surprise but str[j+counter] when j+counter > str.length return undefined and the same as j-counter <0. There for, your while loop never end because of undefined === undefined.
Returning same sized array to handle nested palis.
ex: abxyxZxyxab => 00030703000 odd numbered nested palis.
ex: asddsa => 003000 even numbered pali.
ex: asdttqwe => 00020000 i dont know if this is a pali but here we go
smallest pali is 2 char wide so i start at index:1 and increment till str.len-1
for (var i = 1; i < str.length-1; i++) {
counter=0;
while(str[i]+1-counter == str[i]+counter || str[i]-counter == str[i]+counter) { // always true when counter is 0
// while (even numbered palis || odd numbered palis)
// IF counter is bigger than 0 but we are still here we have found a pali & middle of the pali is i(or i+0.5) &size of the pali is counter*2(or+1)
if(str[i]+1-counter == str[i]+counter){//even sized pali
res[i]=counter*2;
}else{//odd sized pali
res[i]=counter*2+1;
}
counter++;//see if its a bigger pali.
}
}
not super optimized while + if,else checks same stuff. These can be somehow merged. Maybe even even and odd can be handled without any checks.
You don't need to use three loops. You can do it with two for loops where one starts from the beginning and other one is from the end of the string.
Here we use array reverse() method to match palindromes.
Also I added additional minLength parameter and duplication removal logic to make it more nice.
function findPalindromes(str, minLength) {
var palindromes = [];
var _strLength = str.length;
for (var i = 0; i < _strLength; i++) {
for (var j = _strLength - 1; j >= 0; j--) {
if (str[i] == str[j]) {
var word = str.substring(i, j + 1);
//Check if the word is a palindrome
if (word === word.split("").reverse().join("")) {
//Add minimum length validation and remove duplicates
if(word.length >= minLength && palindromes.indexOf(word) === -1){
palindromes.push(word);
}
}
}
}
}
return palindromes;
}
var result = findPalindromes('asdfmadamasdfbigccbigsdf', 2)
console.log(result)
Let's assume I have two variables. One an array of numbers and the other the number 3. The goal is to iterate through the array of numbers and figure out which pair of numbers can be used to equal the number 3 either by being added together or subtracted.
var numbers = [-1, -1, 4, 2, 3, 5, 0]
var target = 3
for(i = 0; i < numbers.length; i++) {
}
I understand the for loop is going to go through the array of numbers but once I do that I don't understand how I can check every pair and see if they add or subtract to hit the value of 3. Is there a JavaScript method that can help?
Not sure if I understood correctly, but maybe something like this?
var numbers = [-1, -1, 4, 2, 3, 5, 0];
var target = 3;
var pairs = [];
for (i = 0; i < numbers.length; i++) {
for (j = 0; j < numbers.length; j++) {
if (j != i) {
if ((numbers[i] + numbers[j]) == target) {
pairs.push([numbers[i], numbers[j]]);
document.write(numbers[i] + " + " + numbers[j] + " = " + target + "<br>");
}
}
}
}
Basically you go through each number in the array, then loop again through all the numbers and check if their sum equals to the target.
You can test it here.
I don't think there is a JavaScript method for this, but this should work:
for(i = 0; i < numbers.length; i++) {
// calculate the difference
var diff = target - numbers[i];
// now: numbers[i] + diff === target
// do whatever you want with diff
}
for (var i = 0; i < numbers.length-1; i++){
for (var j = i+1; j < numbers.length; j++){
if(numbers[i] + numbers[j] == target || Math.abs(numbers[i] - numbers[j]) == target){
console.log(numbers[i]+" , "+numbers[j]); //Do whatever you want
}
}
}
I am trying to write a jQuery that will find the index of a specific value within a 7x7 2D array.
So if the value I am looking for is 0 then I need the function to search the 2D array and once it finds 0 it stores the index of the two indexes.
This is what I have so far, but it returns "0 0" (the initial values set to the variable.
Here is a jsFiddle and the function I have so far:
http://jsfiddle.net/31pj8ydz/1/
$(document).ready( function() {
var items = [[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,0,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7]];
var row = 0;
var line = 0;
for (i = 0; i < 7; ++i) {
for (j = 0; i < 7; ++i) {
if (items[i, j] == '0,') {
row = i;
line = j;
}
}
}
$('.text').text(row + ' ' + line);
});
HTML:
<p class="text"></p>
Your if statement is comparing
if (items[i, j] == '0,')
Accessing is wrong, you should use [i][j].
And your array has values:
[1,2,3,4,5,6,7]
....
Your value '0,' is a string, which will not match numeric values inside the array, meaning that your row and line won't change.
First, you are accessing your array wrong. To access a 2D array, you use the format items[i][j].
Second, your array doesn't contain the value '0'. It doesn't contain any strings. So the row and line variables are never changed.
You should change your if statement to look like this:
if(items[i][j] == 0) {
Notice it is searching for the number 0, not the string '0'.
You access your array with the wrong way. Please just try this one:
items[i][j]
When we have a multidimensional array we access the an element of the array, using array[firstDimensionIndex][secondDimensionIndex]...[nthDimensionIndex].
That being said, you should change the condition in your if statement:
if( items[i][j] === 0 )
Please notice that I have removed the , you had after 0. It isn't needed. Also I have removed the ''. We don't need them also.
There are following problems in the code
1) items[i,j] should be items[i][j].
2) You are comparing it with '0,' it should be 0 or '0', if you are not concerned about type.
3) In your inner for loop you should be incrementing j and testing j as exit condition.
Change your for loop like bellow and it will work
for (i = 0; i < 7; i++) {
for (j = 0; j < 7; j++) {
if (items[i][j] == '0') {
row = i;
line = j;
}
}
}
DEMO
Note:-
1) Better to use === at the place of ==, it checks for type also. As you see with 0=='0' gives true.
2) Better to say i < items.length and j<items[i].length instead of hard-coding it as 7.
var foo;
items.forEach(function(arr, i) {
arr.forEach(function(val, j) {
if (!val) { //0 coerces to false
foo = [i, j];
}
}
}
Here foo will be the last instance of 0 in the 2D array.
You are doing loop wrong
On place of
for (i = 0; i < 7; ++i) {
for (j = 0; i < 7; ++i) {
if (items[i, j] == '0,') {
row = i;
line = j;
}
}
}
use this
for (i = 0; i < 7; i++) {
for (j = 0; j < 7; j++) {
if (items[i][j] == 0) {
row = i;
line = j;
}
}
}
Here is the demo
looks like you are still learning how to program. But here is an algorithm I've made. Analyze it and compare to your code ;)
var itens = [[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,0,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7]];
var row = null;
var collumn = null;
for (var i = 0; i < itens.length; i++) {
for (var j = 0; j < itens[i].length; j++) {
if (itens[i][j] == 0) {
row = i;
collumn = j;
}
}
}
console.log(row, collumn);