I'm trying to find a solution for this problem, in JavaScript, with O(N) time complexity.
Problem:
You are given an array A of N positive integers and an integer k. You want to remove k consecutive elements from A such that the amplitude of remaining element is minimal. Amplitude is the the difference between the minimal and maximal elements.
For eg. A[] = [8,7,4,1] and k=2. Output should be 1 because we will remove 4 and 1.
A brute force solution is simple. Is it possible to do in O(n)? Thanks
Does this help you? I first determine the 3 largest numbers (3 because we remove 2 consecutive numbers and it is possible that those 2 numbers are the 2 largest ones, so we need the next largest), then we do the same for the 3 smallest numbers.
We create an array of the consecutive numbers removed, without altering the original array.
Then we just run some if else statements to determine if the max, min is contained in the consecutive numbers removed
It is not the prettiest though. A lot of if/else
const arr = [8, 7, 4, 1]
const arr2 = [8, 7, 4, 1, 4, 6, 8]
const arr3 = [8, 7, 4, 1, 4, 6, 8, 3, 11, 4, 15]
function slice2Consecutive(arr) {
let newArr = []
for (let i = 0; i < arr.length - 1; i++) {
let s1 = arr[i]
let s2 = arr[i + 1]
newArr.push([arr[i], arr[i + 1]])
}
return newArr
}
function maxThree(arr) {
let one = -Infinity;
let two = -Infinity;
let three = -Infinity;
for (let i = 0; i < arr.length; i += 1) {
let num = arr[i];
if (num > three) {
if (num >= two) {
three = two;
if (num >= one) {
two = one;
one = num;
} else {
two = num;
}
} else {
three = num;
}
}
}
return [one, two, three]
}
function minThree(arr) {
let one = +Infinity;
let two = +Infinity;
let three = +Infinity;
for (let i = 0; i < arr.length; i += 1) {
let num = arr[i];
if (num < three) {
if (num <= two) {
three = two;
if (num <= one) {
two = one;
one = num;
} else {
two = num;
}
} else {
three = num;
}
}
}
return [one, two, three]
}
function minAmplitude(arr) {
const [max, secondMax, thirdMax] = maxThree(arr)
const [min, secondMin, thirdMin] = minThree(arr)
const slicedArr = slice2Consecutive(arr)
const amplitudeArr = []
for (let i = 0; i < slicedArr.length; i++) {
let m = max
let n = min
if (slicedArr[i][0] === max || slicedArr[i][1] === max) {
if (slicedArr[i][0] === secondMax || slicedArr[i][1] === secondMax) {
m = thirdMax
} else {
m = secondMax
}
}
if (slicedArr[i][0] === min || slicedArr[i][1] === min) {
if (slicedArr[i][0] === secondMin || slicedArr[i][1] === secondMin) {
n = thirdMin
} else {
n = secondMin
}
}
amplitudeArr.push(m - n)
}
return Math.min(...amplitudeArr)
}
console.log(minAmplitude(arr))
console.log(minAmplitude(arr2))
console.log(minAmplitude(arr3))
I am practing at hackerrank and I have an exercise with
two-dimensional matrix. I am facing an error in my implementation
11 2 4
4 5 6
10 8 -12
I need to sum across the primary diagonal: 11 + 5 - 12 = 4 after the other diagonal 4 + 5 +10 = 19 finally 19 - 4 = 15
function diagonalDifference(arr) {
var sumRigth = 0;
var sumLeft = 0;
var array = new Array();
for(var i = 0; i < arr.length ; i++ ){
for(var j = 0; j < arr[i].length; j++){
array.push(arr[i][j]);
}
}
for (var i = 0 ; i < array.length; i = i + 4){
sumRigth += array[i];
}
for (var j = 2 ; j < array.length - 1 ; j = j + 2 ){
sumLeft += array[j];
}
return sumLeft - sumRigth;
}
you can try this
function sumDiagonal(matrix) {
let firstSum = 0, secondSum = 0;
for (let row = 0; row < matrix.length; row++) {
firstSum += matrix[row][row];
secondSum += matrix[row][matrix.length - row - 1];
}
console.log(firstSum + ' ' + secondSum);
console.log(firstSum-secondSum);
}
sumDiagonal([[11,2,4],[4,5,6],[10,8,-12]]);
I don't think you're on the right path. A general solution would first sum the elements from top-left to bottom-right (saved here as sumRigth). Then, sum the elements from top-right to bottom-left (saved here as sumLeft). I took it for granted that arrays contain numbers and are of the same size.
function diagonalDifference(array) {
let sumRigth = 0, sumLeft = 0, count = 0;
for (var i = 0 ; i < array.length; i++){
sumRigth += array[i][count++];
}
count = array.length-1;
for (var i = 0; i < array.length; i++){
sumLeft += array[i][count--];
}
return sumLeft - sumRigth;
}
let arr = [
[11, 2, 4],
[4, 5, 6],
[10, 8, -12]
];
console.log(diagonalDifference(arr));
You could take a single loop and get two values dierctly for summing.
function getValue(matrix) {
let sum = 0;
for (let i = 0, l = matrix.length; i < l; i++)
sum += matrix[i][l - i - 1] - matrix[i][i];
return sum;
}
console.log(getValue([[11, 2, 4], [4, 5, 6], [10, 8, -12]]));
I am trying to generate sprial matrix in javascript.
question
Given an integer A, generate a square matrix filled with elements from 1 to A^2 in spiral order.
input : 3
[ [ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ] ]
when input is 4
[ [1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7] ]
my approach is to create 2d array with 0 value and after that they will fill values.
let generateMatrix = function(A) {
let arr = [], counter = 1;
for (let i = 0; i < A; i++) {
let items = []
for (let j = 0; j < A; j++) {
items.push(0)
}
arr.push(items)
}
var spiralMatrix = function(arr) {
if (arr.length > 1) {
for (let i = 0; i < arr[0].length; i++) {
arr[0][i] = counter++;
}
}
return arr
}
return spiralMatrix(arr)
}
console.log(generateMatrix(2))
You could take loops for each edges and loop until no more ranges are avaliable.
function spiral(length) {
var upper = 0,
lower = length - 1,
left = 0,
right = length - 1,
i = 0,
j = 0,
result = Array.from({ length }, _ => []),
value = 1;
while (true) {
if (upper++ > lower) break;
for (; j < right; j++) result[i][j] = value++;
if (right-- < left) break;
for (; i < lower; i++) result[i][j] = value++;
if (lower-- < upper) break;
for (; j > left; j--) result[i][j] = value++;
if (left++ > right) break;
for (; i > upper; i--) result[i][j] = value++;
}
result[i][j] = value++;
return result;
}
var target = document.getElementById('out'),
i = 10;
while (--i) target.innerHTML += spiral(i).map(a => a.map(v => v.toString().padStart(2)).join(' ')).join('\n') + '\n\n';
<pre id="out"></pre>
This bit of code should do what you are trying to.
// This is your Editor pane. Write your JavaScript hem and
// use the command line to execute commands
let generateMatrix = function(A) {
let arr = [],
counter = 1;
for (let i = 0; i < A; i++) {
let items = [];
for (let j = 0; j < A; j++) {
items.push(0);
}
arr.push(items);
}
var spiralMatrix = function(arr) {
let count = 1;
let k = 0; // starting row
let m = arr.length; // ending row
let l = 0; // starting column
let n = arr[0].length; //ending column
while (k < m && l < n) {
// top
for (var i = l; i < n; i++) {
arr[k][i] = count;
count++;
}
k++;
// right
for (var i = k; i < m; i++) {
arr[i][n - 1] = count;
count++;
}
n--;
// bottom
if (k < m) {
for (var i = n - 1; i >= l; i--) {
arr[m - 1][i] = count;
count++;
}
m--;
}
// left
if (l < n) {
for (var i = m - 1; i >= k; i--) {
arr[i][l] = count;
count++;
}
l++;
}
}
return arr;
};
return spiralMatrix(arr);
};
console.log(generateMatrix(4));
This is in some ways the reverse of an answer I gave to another question. We can recursively build this up by slicing out the first row and prepending it to the result of rotating the result of a recursive call on the remaining numbers:
const reverse = a =>
[...a] .reverse ();
const transpose = m =>
m [0] .map ((c, i) => m .map (r => r [i]))
const rotate = m =>
transpose (reverse (m))
const makeSpiral = (xs, rows) =>
xs .length < 2
? [[... xs]]
: [
xs .slice (0, xs .length / rows),
... rotate(makeSpiral (xs .slice (xs .length / rows), xs.length / rows))
]
const range = (lo, hi) =>
[...Array (hi - lo + 1)] .map ((_, i) => lo + i)
const generateMatrix = (n) =>
makeSpiral (range (1, n * n), n)
console .log (generateMatrix (4))
A sharp eye will note that rotate is different here from the older question. transpose (reverse (m)) returns a clockwise rotated version of the input matrix. reverse (transpose (m)) returns a counter-clockwise rotated one. Similarly, here we rotate the result of the recursive call before including it; whereas in the other question we recurse on the rotated version of the matrix. Since we're reversing that process, it should be reasonably clear why.
The main function is makeSpiral, which takes an array and the number of rows to spiral it into and returns the spiraled matrix. (If rows is not a factor of the length of the array, the behavior might be crazy.) generateMatrix is just a thin wrapper around that to handle your square case by generating the initial array (using range) and passing it to makeSpiral.
Note how makeSpiral works with rectangles other than squares:
makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 2) //=>
// [
// [ 1, 2, 3, 4, 5, 6],
// [12, 11, 10, 9, 8, 7]
// ]
makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 3) //=>
// [
// [ 1, 2, 3, 4],
// [10, 11, 12, 5],
// [ 9, 8, 7, 6]
// ]
makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 4) //=>
// [
// [ 1, 2, 3],
// [10, 11, 4],
// [ 9, 12, 5],
// [ 8, 7, 6]
// ]
makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 6) //=>
// [
// [ 1, 2],
// [12, 3],
// [11, 4],
// [10, 5],
// [ 9, 6],
// [ 8, 7]
// ]
The other functions -- range, reverse, transpose, and rotate -- are general purpose utility functions for working with arrays or matrices.
Here's one solution.
I keep the current "moving direction" in dx and dy, such that the next matrix element indices are given by x+dx and y+dy.
If the next item is already filled or is out of bounds, I change this direction clockwise. Otherwise, I fill it with the next value.
const size = 6;
const matrix = Array(size).fill().map(() => Array(size).fill(0));
let x = -1;
let y = 0;
let dx = 1;
let dy = 0;
function changeDirection() {
if (dx === 1) {
dx = 0;
dy = 1;
} else if (dy === 1) {
dy = 0;
dx = -1;
} else if (dx === -1) {
dx = 0;
dy = -1;
} else {
dx = 1;
dy = 0;
}
}
for (let i = 0; i < size * size; i++) {
const yNext = y + dy;
const xNext = x + dx;
const nextRow = matrix[yNext] || [];
const nextItemContent = nextRow[xNext];
if (nextItemContent === undefined || nextItemContent > 0) {
changeDirection();
i--;
continue;
}
y = yNext;
x = xNext;
matrix[y][x] = i + 1;
}
const result = document.getElementById('result');
matrix.forEach(row => {
row.forEach(value => {
result.innerHTML += value.toString().padStart(3);
});
result.innerHTML += '\n';
});
<pre id="result"></pre>
I'm calculating the index, each number should go in a linear array
console.clear();
Array.prototype.range = function(a, b, step) {
step = !step ? 1 : step;
b = b / step;
for(var i = a; i <= b; i++) {
this.push(i*step);
}
return this;
};
const spiral = function(dimen) {
"use strict";
const dim = dimen;
const dimw = dim;
const dimh = dim;
var steps = [1, dimh, -1, -dimh];
var stepIndex = 0;
var count = 1;
var countMax = dimw
var dec = 0
var index = 0;
var arr = [];
arr = arr.range(1, dimh * dimw)
const newArr = arr.reduce((coll, x, idx) => {
index += steps[stepIndex]
coll[index-1] = idx+1;
if (count === countMax) {count = 0; stepIndex++; dec++;}
if (dec === 1) {dec = -1; countMax--}
if (stepIndex == steps.length) {stepIndex = 0}
count++;
return coll;
}, []);
var ret = []
while (newArr.length) {
ret.push(newArr.splice(0,dimw))
}
return ret
}
console.log(spiral(3))
console.log(spiral(4))
console.log(spiral(5))
var n=14; // size of spiral
var s=[]; // empty instruction string
function emp() {} // no move
function xpp() {xp++;} // go right
function xpm() {xp--;} // go left
function ypp() {yp++;} // go down
function ypm() {yp--;} // go up
var r=[xpp,ypp,xpm,ypm]; // instruction set
s.push(emp); // push 'no move' (used for starting point)
var c=n-1;
while (c-->0) s.push(r[0]); // push first line - uses a different rule
for (var i=1;i<2*n-1;i++) { // push each leg
c=Math.floor((2*n-i)/2);
while (c-->0) s.push(r[i%4]);
}
var sp=new Array(n); // spiral array
for (var i=0;i<n;i++) sp[i]=new Array(n);
var xp=0; // starting position
var yp=0;
for (var i=0;i<n*n;i++) {
s[i](); // execute next instruction
sp[yp][xp]=i+1; // update array
}
for (var i=0;i<n;i++) console.log(sp[i].toString()); // log to console
This code makes a macro of functions to generate a run sequence, for example:
'right4, down4, left4, up3, right3, down2, left2, up1, right1
and then implements it.
Here is a solution to Spiral Matrix from leetcode, maybe this can help
https://leetcode.com/problems/spiral-matrix/
var spiralOrder = function(matrix) {
if (matrix.length == 0) {
return [];
}
let result = [];
let rowStart = 0;
let rowEnd = matrix.length - 1;
let colStart = 0;
let colEnd = matrix[0].length - 1;
while (true) {
// top
for (let i = colStart; i <= colEnd; i++) {
result.push(matrix[rowStart][i]);
}
rowStart++;
if (rowStart > rowEnd) {
return result;
}
// right
for (let i = rowStart; i <= rowEnd; i++) {
result.push(matrix[i][colEnd]);
}
colEnd--;
if (colEnd < colStart) {
return result;
}
// bottom
for (let i = colEnd; i >= colStart; i--) {
result.push(matrix[rowEnd][i]);
}
rowEnd--;
if (rowEnd < rowStart) {
return result;
}
// left
for (let i = rowEnd; i >= rowStart; i--) {
result.push(matrix[i][colStart]);
}
colStart++;
if (colStart > colEnd) {
return result;
}
}
return result;
};
console.log(
spiralOrder([[2, 3, 4], [5, 6, 7], [8, 9, 10], [11, 12, 13], [14, 15, 16]])
);
console.log(spiralOrder([[7], [9], [6]]));
console.log(spiralOrder([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]));
console.log(spiralOrder([[1, 2, 3], [4, 5, 6], [7, 8, 9]]));
Here's my answer using only one for loop -
function matrix(n) {
const arr = [];
let row = 0;
let column = 0;
let counter = 1;
let edge = n - 1;
let leftToRightRow = false;
let topToBottomCol = false;
let rightToLeftRow = false;
let bottomToTopCol = false;
for (i = 0; i < n * n; i++) {
if (column <= edge && !leftToRightRow) {
if (!Array.isArray(arr[row])) {
arr[row] = []; // if array is not present at this index, then insert one
}
arr[row][column] = counter;
if (column == edge) {
row = row + 1;
leftToRightRow = true;
} else {
column = column + 1;
}
counter = counter + 1;
} else if (column === edge && !topToBottomCol) {
if (!Array.isArray(arr[row])) {
arr[row] = []; // if array is not present at this index, then insert one
}
arr[row][column] = counter;
if (row === edge) {
column = column - 1;
topToBottomCol = true;
} else {
row = row + 1;
}
counter = counter + 1;
} else if (column >= 0 && !rightToLeftRow) {
arr[row][column] = counter;
if (column === 0) {
row = row - 1;
rightToLeftRow = true;
} else {
column = column - 1;
}
counter = counter + 1;
} else if (row >= n - edge && !bottomToTopCol) {
arr[row][column] = counter;
if (row === n - edge) {
column = column + 1;
bottomToTopCol = true;
//setting these to false for next set of iteration
leftToRightRow = false;
topToBottomCol = false;
rightToLeftRow = false;
edge = edge - 1;
} else {
row = row - 1;
}
counter = counter + 1;
}
}
return arr;
}
Solution is implemented in C++, but only logic matter then you can do it in any language:
vector<vector<int> > Solution::generateMatrix(int A) {
vector<vector<int>> result(A,vector<int>(A));
int xBeg=0,xEnd=A-1;
int yBeg=0,yEnd=A-1;
int cur=1;
while(true){
for(int i=yBeg;i<=yEnd;i++)
result[xBeg][i]=cur++;
if(++xBeg>xEnd) break;
for(int i=xBeg;i<=xEnd;i++)
result[i][yEnd]=cur++;
if(--yEnd<yBeg) break;
for(int i=yEnd;i>=yBeg;i--)
result[xEnd][i]=cur++;
if(--xEnd<xBeg) break;
for(int i=xEnd;i>=xBeg;i--)
result[i][yBeg]=cur++;
if(++yBeg>yEnd) break;
}
return result;
}
Solition in c#:
For solving this problem we use loops for each moving directions
public IList<int> SpiralOrder(int[][] matrix) {
var result = new List<int>();
var n = matrix[0].Length;
var m = matrix.Length;
var i = 0;
var j = 0;
var x = 0;
var y = 0;
while (true)
{
//left to right moving:
while (x <= n - 1 - i)
{
result.Add(matrix[y][x]);
x++;
}
if (result.Count == n * m)
return result;
x--;y++;
//up to down moving:
while (y <= m - 1 - j)
{
result.Add(matrix[y][x]);
y++;
}
if (result.Count == n * m)
return result;
y--;x--;
//right to left moving:
while (x >= j)
{
result.Add(matrix[y][x]);
x--;
}
if (result.Count == n * m)
return result;
x++;y--;
//down to up moving:
while (y > j)
{
result.Add(matrix[y][x]);
y--;
}
if (result.Count == n * m)
return result;
y++;x++;
i++;
j++;
}
}
I've been struggling for a little while to find or figure out algorithm.
The task:
Basically, I have an array of probabilities:
var input = [0.1, 0.2, 0.3, 0.1];
Let's name these inputs accordingly to: A, B, C and D.
And I also have a variable "m", which can tell me how many of these things needs to happen in order to get the result.
For example:
var m = 2;
This variable m is telling me that the event will happen if any of those two (or more) probabilities will happen.
So in this case, for event to happen, all possible ways for event to happen is:
ABCD
ABC
ABD
BCD
AB
AC
AD
BC
BD and CD
Now I need to calculate their probabilities, which I already have algorithms to calculate AND and OR (where input is just a probabilities array).
AND:
if (input.length > 0) {
output = 1;
}
for (i = 0; i < input.length; i++) {
output = input[i] * output;
}
OR:
if (input.length > 0) {
output = input[0];
}
for (i = 1; i < input.length; i++) {
output = (output + input[i]) - (output * input[i]);
}
So I am struggling on figuring out how to loop through all possible possibilities... And to have something like:
(A and B and C and D) or (A and B and C) or (A and B and D)... and so on... I hope you get the idea.
Here's a simple non-recursive solution to enumerate all combinations with at least m elements.
range = n => [...Array.from({length: n}).keys()]
mask = xs => b => xs.filter((_, n) => b & (1 << n))
at_least = n => xs => xs.length >= n
//
a = [...'ABCD']
m = 2
result = range(1 << a.length).map(mask(a)).filter(at_least(m))
console.log(result.map(x => x.join('')))
Since JS bit arithmetics is limited to 32 bits, this only works for m < 32.
You could get the combinations of your desired array with a minimum of two by using a recursive function which generates all the possible combinations.
function getC(array, min) {
function iter(i, temp) {
var t = temp.concat(array[i]);
if (i === array.length) return;
iter(i + 1, t);
iter(i + 1, temp);
if (t.length >= min) {
result.push(t);
}
}
var result = [];
iter(0, []);
return result;
}
var input = [0.1, 0.2, 0.3, 0.1];
console.log(getC(input, 2).map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could go over all combimations of 2 elements (AB, CD etc.) with two nested loops:
for(let i = 0; i < input.length; i++) {
for(let j = i + 1; j < input.length; j++) {
// possible combination: i and j
for(let k = j; k < input.length; k++) {
// possible combination: i, j, k
// and so on
}
}
}
for at least m elements that can be generalized with a nested generator that generates an array of indices ([0, 1], [0, 2], [1, 2], [0, 1, 2]):
function* combinations(length, m = 1, start = 0) {
// Base Case: If there is only one index left, yield that:
if(start === length - 1) {
yield [length - 1];
return;
}
// Otherwise go over all left indices
for(let i = start; i < length; i++) {
// And get all further combinations, for 0 that will be [1, 2], [1] and [2]
for(const nested of combinations(length, m - 1, i + 1)) {
// Yield the nested path, e.g. [0, 1], [0, 1, 2] and [0, 2]
yield [i, ...nested];
}
// If the minimum length is already reached yield the index itself
if(m <= 1) yield [i];
}
}
Now for every combination, we just have to multiply the probabilities and add them up:
let result = 0;
for(const combination of combimations(input.length, m))
result += combination.reduce((prev, i) => prev * input[i], 1);
I am just starting with JS and need some help with calculating a gcd.
I would like to calculate the gcd for every combination of two elements from two arrays.
I mean: for each element A[i] from array A, for each element B[j] from B, calculate the gcd value of A[i] and B[j] and print it in the console. I do have 16 prints, but they are not correct. I use Euclid's algorithm to calculate it and it looks like the A[i] value is overwritten. I have no idea why. Could someone help me? This is my code:
var n = 4;
var A = [2, 5, 6, 7];
var B = [4, 9, 10, 12];
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
while (A[i] != B[j]) {
if (A[i] < B[j]) {
B[j] = B[j] - A[i];
} else {
A[i] = A[i] - B[j];
}
}
console.log(A[i]);
}
}
You are modifying your array elements while performing euclid's algorithm. I recommend creating a separate function for this algorithm, like:
var n = 4;
var A = [2, 5, 6, 7];
var B = [4, 9, 10, 12];
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
console.log(euclid(A[i], B[j]));
}
}
function euclid(a, b) {
while (b != 0) {
var r = a % b;
a = b;
b = r;
}
return a;
}
Edit:
You can make and use a storage array in the following way:
var C = []; // The array that will contain the arrays
for (var i = 0; i < n; i++) {
C[i] = []; // "Inner array"
for (var j = 0; j < n; j++) {
C[i][j] = euclid(A[i], B[j]);
console.log(C[i][j]);
}
}
Without complicationg your algorithm , use forEach as following :
const A = [2, 5, 6, 7];
const B = [4, 9, 10, 12];
const gcd = (x, y) => (!y) ? x : gcd(y, (x % y));
A.forEach((a, i) => {
B.forEach((b, j) => {
console.log(
`GCD(A[${i}]=${a}, B[${j}]=${b}) =`, gcd(a, b)
);
});
})