Given the triangle of consecutive odd numbers:
1
3 5
7 9 11
13 15 17 19
21 23 25 27 29
// Calculate the row sums of this triangle from the row index (starting at index 1) e.g.:
rowSumOddNumbers(1); // 1
rowSumOddNumbers(2); // 3 + 5 = 8
I tried to solve this using for loops:
function rowSumOddNumbers(n){
let result = [];
// generate the arrays of odd numbers
for(let i = 0; i < 30; i++){
// generate sub arrays by using another for loop
// and only pushing if the length is equal to current j
let sub = [];
for(let j = 1; j <= n; j++){
// if length === j (from 1 - n) keep pushing
if(sub[j - 1].length <= j){
// and if i is odd
if(i % 2 !== 0){
// push the i to sub (per length)
sub.push(i);
}
}
}
// push everything to the main array
result.push(sub);
}
// return sum of n
return result[n + 1].reduce(function(total, item){
return total += item;
});
}
My code above is not working. Basically I was planning to 1st generate an array of odd numbers less than 30. Next I need to create a sub array base on the length of iteration (j) that would from 1 - n (passed). Then finally push it to the main array. And then use reduce to get the sum of all the values in that index + 1 (since the index starts at 1).
Any idea what am I missing and how to make this work?
Most code problems involve some analysis first in order to spot patterns which you can then convert into code. Looking at the triangle, you'll see the sum of each row follows a pattern:
1: 1 === 1 ^ 3
2: 3 + 5 = 8 === 2 ^ 3
3: 7 + 9 + 11 = 27 === 3 ^ 3
... etc
So from the analysis above you can see that your code could probably be simplified slightly - I won't post an answer, but think about using Math.pow.
No need for any loops.
function rowSumOddNumbers(n) {
// how many numbers are there in the rows above n?
// sum of arithmetic sequence...
let numbers_before_n_count = (n - 1) * n / 2;
let first_number_in_nth_row = numbers_before_n_count * 2 + 1;
let last_number_in_nth_row = first_number_in_nth_row + 2 * (n - 1);
// sum of arithmetic sequence again...
return n * (first_number_in_nth_row + last_number_in_nth_row) / 2;
}
Related
Can someone explain to me why my fibonacciGenerator function doesn't work with this code? I understand why it works with the second code tho but I just don't get why the first one doesn't.
function fibonacciGenerator(n) {
if (n > 0) {
var fArray = [];
fArray.push(0);
if (n >= 2) {
fArray.push(1);
}
for (var i = 0; i < n; i++) {
fArray.push(fArray[i] + fArray[i + 1]);
}
console.log(fArray);
}
}
fibonacciGenerator(1);
fibonacciGenerator(2);
Second code working :
function fibonacciGenerator(n) {
if (n > 0) {
var fArray = [];
fArray.push(0);
if (n >= 2) {
fArray.push(1);
}
for (var i = 2; i < n; i++) {
fArray.push(fArray[i - 1] + fArray[i - 2]);
}
console.log(fArray);
}
}
fibonacciGenerator(1);
fibonacciGenerator(2);
The first code is printing 2 extra Fibonacci number this is because:
you are first pushing 0 and 1 into the array as:
var fArray = [];
fArray.push(0);
if (n >=2 ){
fArray.push(1);
}
and then you loop over again till n times. Because of this reason it prints two extra Fibonacci numbers.
the solution is to either loop over n-2 time or to use the second code.
var fArray = [];
fArray.push(0);
if (n >= 2) {
fArray.push(1);
}
The initial condition is to cover n=1: [0] and n=2: [0,1]
The 2nd code is working because the loop only starts when n is greater than i, so means it skips the loop with n < 2.
For your problem, you don't skip the loop when n < 2.
for (var i = 0; i < n; i++) {
fArray.push(fArray[i] + fArray[i + 1]);
}
You can imagine the result will be like below when n < 2 with your loop.
Note that the inital value is fArray = [0]
fArray.push(fArray[0] + fArray[1]); //fArray[1] is undefined because you only have 1 item in your array
In this case fArray[0] + fArray[1] ==> 0 + undefined = NaN
So that's why your logic does not work when n < 2
To correct it, you need to avoid the loop if n < 2
//if n=1 or n=2, it won't trigger the loop due to `i < n-2`
for (var i = 0; i < n-2; i++) {
fArray.push(fArray[i] + fArray[i + 1]);
}
The idea to have i start with 0 instead of 2, and to adjust the body of the loop accordingly, is fine, but there is one thing that the first version didn't adjust: the stop condition of the loop.
By setting i=0, the first version loops 2 times more than the second version. You should also alter the end condition in the same way: instead of i < n, it should have i < n - 2, so to ensure the number of iterations is the same as in the second version.
Not related to your question, but the console.log should better be placed outside of the function. The job of the function should be to return the array, not to print it. So also, when n > 0 is false, it should return an empty array.
function fibonacciGenerator(n) {
var fArray = [];
if (n > 0) {
fArray.push(0);
if (n >= 2) {
fArray.push(1);
}
for (var i = 0; i < n - 2; i++) {
fArray.push(fArray[i] + fArray[i + 1]);
}
}
return fArray;
}
console.log(fibonacciGenerator(1));
console.log(fibonacciGenerator(2));
First you have to identify the pattern.
Fibonacci series -> 0 1 1 2 3 5 8 13 21
Term -> 0 1 2 3 4 5 6 7 8
0th term =0, 1st term =1
From the second term,
2nd = 1st term + 0th term = 1+0 = 1
3rd = 2nd term + 1st term = 1+1 = 2
4th = 3rd term + 2nd term = 2+1 = 3
5th = 4th term + 3rd term = 3+2 = 5
nth = (n-1) + (n-2)
since the first 2 terms are fixed, you have to start for loop from i= 2.
Also, according to the above shown pattern, you have to use following code inside the for loop.
fArray.push(fArray[i - 1] + fArray[i-2]);
This question already has answers here:
Looping through array and removing items, without breaking for loop
(17 answers)
Closed 2 years ago.
I'm making a function to create a list of prime numbers from 0 to num. I start off with a list of integers from 2 to num, and iterate over each one that goes from 2 to i < num; if at any point item % i === 0, the item is removed from the list. This works fine:
function getPrimes(num) {
// get list of ints from 2 to num
let primes = [...Array(num + 1).keys()];
primes = primes.splice(2);
let lastNumber = primes[primes.length - 1];
// make iterable, run its loop
// for each number in primes
for (let number of primes) {
// use iterable to remove if not prime
for (let i = 2; i < num; i++) {
if (number % i === 0) {
primes.splice(primes.indexOf(number), 1);
}
}
}
// add back two
primes.unshift(2);
return primes;
But when I try and make the iterable for each number only to up to Math.floor(num / 2) for the sake of efficiency, it breaks the code somehow:
function getPrimes(num) {
// get list of ints from 2 to num
let primes = [...Array(num + 1).keys()];
primes = primes.splice(2);
let lastNumber = primes[primes.length - 1];
// make iterable, run its loop
// for each number in primes
for (let number of primes) {
// use iterable to remove if not prime
for (let i = 2; i < Math.floor(num / 2); i++) {
if (number % i === 0) {
primes.splice(primes.indexOf(number), 1);
}
}
}
// add back two
primes.unshift(2);
return primes;
When I tried it out, getPrimes(10) gives me [ 2, 3, 5 ]. So seven is missing from the list of prime numbers from 0 to 10. Why is that? I checked and 7 modulo 2, 3, and 4 returns 1, 1, and 3, respectively. So why is the code in the loop running that removes 7 from primes? It's the only place in the code where I put that I wanted to remove a number from the array.
The first issue is that you are looping while removing items, which causes some items to be skipped. Loop backwards instead, so that only items that have already been checked are shifted. Second, num / 2 should be changed to Math.sqrt(number), as that is the maximum factor that needs to be checked before we can be sure that a number is prime. With this method, there is no need to add 2 back to the array.
function getPrimes(num) {
// get list of ints from 2 to num
let primes = [...Array(num + 1).keys()];
primes = primes.splice(2);
let lastNumber = primes[primes.length - 1];
// make iterable, run its loop
// for each number in primes
for(let i = primes.length - 1; i >= 0; i--){
let number = primes[i];
// use iterable to remove if not prime
for (let j = 2; j * j <= number; j++) {
if (number % j === 0) {
primes.splice(i, 1);
break;
}
}
}
return primes;
}
console.log(...getPrimes(10));
Can anyone help me identify the time complexity of the following code?
Background: this is a HackerRank algorithm problem where the editorial section lists the solution with a time complexity of O(n^2) but I think its O(n).
I believe its O(n) because we're only using one loop to traverse the 2 dimensional array and are not using nested loops and only looping over the array once.
Am I correct or am I missing something?
Solution
//arr is a 2 dimensional array containing an equal number of rows and columns
function diagonalDifference(arr) {
let diff = 0;
const length = arr.length - 1;
for (let i = 0; i < arr.length; i++) {
diff += arr[i][i] - arr[i][length - i];
}
return Math.abs(diff);
}
Problem
Given a square matrix (AKA 2D Array), calculate the absolute difference between the sums of its diagonals.
For example, the square matrix arr is shown below:
1 2 3
4 5 6
9 8 9
The left-to-right diagonal = 1 + 5 + 9 = 15. The right to left diagonal = 3 + 5 + 9 = 17. Their absolute difference is |15 - 17| = 2.
Am I correct or am I missing something?
You are right, but I think their categorization of O(n^2) may be due to the interpretation wherein n refers to the n of the input (i.e. the side-length of the matrix). In this case, the number of elements in the matrix itself is exactly n^2, and thus any solution (since any solution must read in all n^2 inputs) is Ω(n^2) (where Ω roughly means "at least").
Your categorization of the solution as O(n) is correct if we say that n refers to the size of the whole input matrix.
The time complexity of the code is O(n) where is the length of the matrix. As you have correctly said the loop is running only once and that too equals the number of rows/ columns viz the length of the matrix. there are no nested loops. So the time complexity is definitely, O(n) for all the cases best, worst, avg.
My solution:
function diagonalDifference(arr) {
let leftDiagSum = 0;
let rightDiagSum = 0;
for (let i = 0; i < arr.length; i++) {
leftDiagSum += arr[i][i];
rightDiagSum += arr[i][arr[i].length - (i + 1)];
}
let sum = Math.abs(leftDiagSum - rightDiagSum);
return sum;
}
You can try this also:
`
function diagonalDifference(arr) {
let firstDiagonalSum = arr[0][0] + arr[1][1] + arr[2][2];
let secondDiagonalSum = arr[0][2] + arr[1][1] + arr[2][0];
let result = (secondDiagonalSum) - (firstDiagonalSum);
return result;
}`
in python :
def diagonalDifference(arr):
d1 = 0
d2 = 0
n = len(arr)
for i in range(0, n):
for j in range(0, n):
if (i == j):
d1 += arr[i][j]
if (i == n - j - 1):
d2 += arr[i][j]
return abs(d1 - d2)
I'm trying to understand how to find all the combinations of a string using a double loop but the solution I've come across is too complicated for my understanding. The function does what I need but I have beginner understanding of setting up a single or double for loop.
I'm hoping for a general step by step explanation of what is going on but for specific questions: what functions are "i < Math.pow(2,n)-1", "((i & (1 << j)) == 1 << j)", and "var comb = ''; (temporary storage?)" serving?
subsets = function(str) {
var n = str.length;
for (var i=1; i< Math.pow(2,n)-1; i++) {
var comb = '';
for (var j=0; j<n; j++) {
var use = ((i & (1 << j)) == 1 << j);
if(use)comb+=str.charAt(j);
}
console.log(comb);
}
}
subsets("age");
Output: a ag ae g ge e
To get a random combination of the string, we could set up a boolean array, storing if one of the characters should be displayed or not, e.g:
"a","g","e"
[true,false,true]
=>"ae"
So the number of possible variations is
2 /*true/false*/ ** str.length
written in old style:
Math.pow(2,str.length)
So the main for loop iterates over all possible combinatons except the first one (as i starts with 1),as that would be an empty string and the last one (-1) that would be "age". While i is an integer which simply counts up, we could also imagine that its a boolean array (in a bitwise view):
integer
bits
boolean array
1
001
[false,false,true]
2
010
[false,true,false]
3
011
[false,true,true]
4
100
[true,false,false]
...
6 < 2 ** 3 -1
110
[true,true,false]
Now the inner loop:
for (var j=0; j<n; j++) {
var use = ((i & (1 << j)) == 1 << j);
if(use)comb+=str.charAt(j);
}
Just goes over our letters and checks if the boolean flag is true, so at i = 5 the boolean array would be:
[true,false,true]//101
and that is converted to
"ae"
How it looks bitwise:
A true one ("a"):
101 // i
&001 //1<<j where j is 0
=001
===
001 //1<<j
A false one ("g"):
101
&010 //1<<j where j is 1
=000
!==
010 //1<<j
A true one ("e"):
101 // i
&100 //1<<j where j is 2
=100
===
100 //1<<j
So it checks if the boolean array (i) is true at js index, if so it adds that letter. BTW shorter:
if(i & (1<<j))
var i=1; i< Math.pow(2,n)-1; i++
What the Math.pow(2, n) - 1 is saying is run this loop until (2^n)-1, where 'n' is the length of the string. So with the input 'age', the first for loop will run while i, starting at 1 and incrementing by 1 each loop, is less than (2^3)-1. Therefore, this first loop will run 6 times.
var comb = ''
Is exactly what you think it is - storage for what to log that populates as the for loops do their thing!
As for (i & (1 << j)) == 1 << j), that's where we get into Bitwise operators! Unfortunately, I don't understand these nearly well enough to explain them :(
Math.pow is a power function. The first argument is the base, and the second argument is the exponent, so Math.pow(2, n) is equivalent to 2^n. In the loop, i< Math.pow(2,n) means the boundary of the for loop is while i is less than 2^n, where n is the string length.
var comb = ''; is initializing an empty string. This string is concatenated later in the loop so this declaration serves to establish that variable for concatenation.
It's a code based on binary (0/1)
operators in javascript explain << it's a "Shift a into binary representation of b bits to the left, by inserting zeros by the right"
and & : Returns a 1 for each bit position for which the corresponding bits of the two operands are 1.
If u had some problem to undestand a code, Try it on paper step by step with simple example.
Try example str = "a", after try "on" ...
For "a" the beginning is
var n = str.length; // 1
for (var i=1; i< Math.pow(2,n)-1; i++) { // for i=1;i<2^1-1 =2-1=1;i++
var comb = '';
for (var j=0; j<n; j++) {//for j=0;j<1;j++
var use = ((i & (1 << j)) == 1 << j);// use = 1 & (1 << 0 insert 0 times 0)) == 1 << 0= (1 & 1)== 1=true (1==1)
if(use)comb+=str.charAt(j);//comb='' + a.charAt(0)= comb= '' + "a"='a'
... You continue the loops.
binary is a method to write number with 0/1 :
Example 00101(binary)
U have 5 digits then the 1rst 0 = 0*2^(number of place of digit from right-1) = 0*2^4=0
Then 00101(binary) = 0*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 1*2^0
= 0 + 0 + 1*4 + 0 + 1*1
= 5 in current using (decimal)
U find lot of explanation on binary with Google
I'm trying to understand the logic in a solution to the Array Addition CoderByte problem. Here is the question prompt -- "Using the JavaScript language, have the function ArrayAdditionI(arr) take the array of numbers stored in arr and return the string true if any combination of numbers in the array can be added up to equal the largest number in the array, otherwise return the string false. For example: if arr contains [4, 6, 23, 10, 1, 3] the output should return true because 4 + 6 + 10 + 3 = 23. The array will not be empty, will not contain all the same elements, and may contain negative numbers."
This is a solution that works, but I get lost with the for loop within the for loop. Why isn't it always the case that i = j since the for loops both start with their counters at 0. So wouldn't it always be 0 = 0?
function ArrayAdditionI(arr) {
arr.sort(function(a,b){return a - b})
var largest = arr.pop();
var sum = 0;
for (var i = 0; i < arr.length; i++){
sum += arr[i];
for (var j = 0; j < arr.length; j++){
if (i != j) {
sum += arr[j];
if (sum == largest) {
return true;
}
}
}
for (var k = 0; k < arr.length; k++) {
if (i != k) {
sum -= arr[k];
if (sum == largest) {
return true;
}
}
}
sum = 0;
}
// code goes here
return false;
}
Thanks!
i_made_that & user3085131:
To further explain the k loop, it is used to work back through and subtract array values in the order that they were initially added, to yield new results not otherwise obtainable.
Without the k loop you can't solve many potential arrays (although it will actually pass the coderbyte test cases due to lack of appropriate test).
Consider [1,2,3,98,100]...this should pass since 2+98 = 100. However it won't without the k loop. If you log the results of sum without the k, you would see:
3 (1 + 2)
6 (3 + 3)
104 (6 + 98)
3 (2 + 1)
6 (3 + 3)
104 (6 + 98)
4 (3 + 1)
6 (4 + 2)
104 (6 + 98)
99 (98 + 1)
101 (99 + 2)
104 (101 + 3)
With the k loop however, on the second iteration of i it will pass as it will subtract 1 from 104, and then 3 from 103 to reach 100.
The thing is, is that you have 2 for loops inside the for loop with the "i" variable.
variable "i" is always going to be 0 until you finish iterating thru the 2 for loops that are inside.
for(var i=0){
for(var j=0){}
for(var k=0){}
}