Simple Feedforward Neural Network in JavaScript - javascript

I'm new to this site, so I apologize in advance if I'm doing anything wrong in this post.
I'm currently trying out machine learning, and I'm learning neural networks. I'm currently using http://neuralnetworksanddeeplearning.com/. However, I don't fully understand everything, and all of the code is written in Python (I'm more comfortable with JavaScript).
I've created a program that works for simple data. However, for more complicated data (handwritten digits recognition with MNIST data), the accuracy rate isn't nearly as high as the website above says it will be, by using a neural network of 784 input neurons, 10-400 hidden neurons in the hidden layer (only one hidden layer and tried several possible number of neurons), and 10 output neurons with hundreds of iterations. I think that there is an error with my back propagation step (i.e. the train step, I'm including the other functions here as reference) that prevents it from learning fast enough (BTW, I'm using the cross-entropy as my cost function). I would really appreciate if anyone can help me find the error. Thanks in advance.
Below is the code. The weights are arranged in an array of arrays of arrays (weight[i][j][k] is the weight between the jth neurons in the ith layer and the kth neuron in the (i+1)th layer). Similarly, bias[i][j] is the bias of the (i+1)th layer for the jth neuron. The training data is formatted as an array of objects with keys of inputs and outputs (see example below).
class NeuralNetwork {
constructor(layers) {
// Check if layers is a valid argument
// Initialize neural network
if (!Array.isArray(layers) || layers.length < 2) {
throw Error("Layers must be specified as an array of length at least 2");
}
this.weights = [];
this.biases = [];
for (let i = 0, l = layers.length; i < l; ++i) {
let currentLayer = layers[i];
if (typeof currentLayer === "number" && Number.isInteger(currentLayer) && currentLayer > 0) {
let numWeights = layers[i + 1];
if (i < l - 1) {
this.weights.push([]);
}
if (i) {
this.biases.push([]);
}
// Seed weights and biases
for (let j = 0; j < currentLayer; ++j) {
if (i < l - 1) {
let weights = [];
for (let k = 0; k < numWeights; ++k) {
weights.push(Math.random() * 2 - 1);
}
this.weights[i].push(weights);
}
if (i) {
this.biases[i - 1].push(Math.random() * 2 - 1);
}
}
} else {
throw Error("Array used to specify NeuralNetwork layers must consist solely of positive integers");
}
}
this.activation = (x) => 1 / (1 + Math.exp(-x));
this.activationDerivative = (x) => this.activation(x) * (1 - this.activation(x));
Object.freeze(this);
console.log("Successfully initialized NeuralNetwork");
return this;
}
run(input, training) {
// Forward propagation
let currentInput;
if (training) {
currentInput = [input.map((a) => {return {before: a, after: a}})];
} else {
currentInput = [...input];
}
for (let i = 0, l = this.weights.length; i < l; ++i) {
let newInput = [];
for (let j = 0, m = this.weights[i][0].length, n = (training ? currentInput[i] : currentInput).length; j < m; ++j) {
let sum = this.biases[i][j];
for (let k = 0; k < n; ++k) {
sum += (training ? currentInput[i][k].after : currentInput[k]) * this.weights[i][k][j];
}
if (training) {
newInput.push({
before: sum,
after: this.activation(sum)
});
} else {
newInput.push(this.activation(sum));
}
}
if (training) {
currentInput.push(newInput);
} else {
currentInput = newInput;
}
}
return currentInput;
}
train(data, learningRate = 0.1, batch = 50, iterations = 10000) {
// Backward propagation
console.log("Initialized training");
let length = data.length,
totalCost = 0,
learningRateFunction = typeof learningRate === "function",
batchCount = 0,
weightChanges = [],
biasChanges = [];
for (let i = 0; i < iterations; ++i) {
let rate = learningRateFunction ? learningRate(i, totalCost) : learningRate;
totalCost = 0;
for (let j = 0, l = length; j < l; ++j) {
let currentData = data[j],
result = this.run(currentData.input, true),
outputLayer = result[result.length - 1],
outputLayerError = [],
errors = [];
for (let k = 0, m = outputLayer.length; k < m; ++k) {
let currentOutputNeuron = outputLayer[k];
outputLayerError.push(currentOutputNeuron.after - currentData.output[k]);
totalCost -= Math.log(currentOutputNeuron.after) * currentData.output[k] + Math.log(1 - currentOutputNeuron.after) * (1 - currentData.output[k]);
}
errors.push(outputLayerError);
for (let k = result.length - 1; k > 1; --k) {
let previousErrors = errors[0],
newErrors = [],
currentLayerWeights = this.weights[k - 1],
previousResult = result[k - 1];
for (let i = 0, n = currentLayerWeights.length; i < n; ++i) {
let sum = 0,
currentNeuronWeights = currentLayerWeights[i];
for (let j = 0, o = currentNeuronWeights.length; j < o; ++j) {
sum += currentNeuronWeights[j] * previousErrors[j];
}
newErrors.push(sum * this.activationDerivative(previousResult[i].before));
}
errors.unshift(newErrors);
}
for (let k = 0, n = this.biases.length; k < n; ++k) {
if (!weightChanges[k]) weightChanges[k] = [];
if (!biasChanges[k]) biasChanges[k] = [];
let currentLayerWeights = this.weights[k],
currentLayerBiases = this.biases[k],
currentLayerErrors = errors[k],
currentLayerResults = result[k],
currentLayerWeightChanges = weightChanges[k],
currentLayerBiasChanges = biasChanges[k];
for (let i = 0, o = currentLayerBiases.length; i < o; ++i) {
let change = rate * currentLayerErrors[i];
for (let j = 0, p = currentLayerWeights.length; j < p; ++j) {
if (!currentLayerWeightChanges[j]) currentLayerWeightChanges[j] = [];
currentLayerWeightChanges[j][i] = (currentLayerWeightChanges[j][i] || 0) - change * currentLayerResults[j].after;
}
currentLayerBiasChanges[i] = (currentLayerBiasChanges[i] || 0) - change;
}
}
++batchCount;
if (batchCount % batch === 0 || i === iterations - 1 && j === l - 1) {
for (let k = 0, n = this.weights.length; k < n; ++k) {
let currentLayerWeights = this.weights[k],
currentLayerBiases = this.biases[k],
currentLayerWeightChanges = weightChanges[k],
currentLayerBiasChanges = biasChanges[k];
for (let i = 0, o = currentLayerWeights.length; i < o; ++i) {
let currentNeuronWeights = currentLayerWeights[i],
currentNeuronWeightChanges = currentLayerWeightChanges[i];
for (let j = 0, p = currentNeuronWeights.length; j < p; ++j) {
currentNeuronWeights[j] += currentNeuronWeightChanges[j] / batch;
}
currentLayerBiases[i] += currentLayerBiasChanges[i] / batch;
}
}
weightChanges = [];
biasChanges = [];
}
}
totalCost /= length;
}
console.log(`Training ended due to iterations reached\nIterations: ${iterations} times\nTime spent: ${(new Date).getTime() - startTime} ms`);
return this;
}
}
Example
Tests if a point is inside a circle. For this example, the neural network performs well. However, for more complicated examples such as handwriting recognition, the neural network performs really badly (best I can get for a single neural network is 70% accuracy, compared to the 96% accuracy stated in the website even when using similar parameters).
let trainingData = [];
for (let i = 0; i < 1000; ++i) {
let [x, y] = [Math.random(), Math.random()];
trainingData.push({input: [x, y], output: [Number(Math.hypot(x,y) < 1)]});
}
let brain = new NeuralNetwork([2, 5, 5, 1]);
brain.train(trainingData.slice(0,700), 0.1, 10, 500); // Accuracy rate 95.33% on the remaining 300 entries in trainingData

Ok, I guess I'm going to answer my own question. So, I don't think there is an error in my code and it's perfectly fine to use (albeit really, really inefficient) if anyone wants to.
The reason why my runs on the MNIST data did not give accurate answers come from the fact that I did not process the data at first. The raw data gave the darkness of the 28*28 pixels in the range of [0, 255], which I used directly as the input for each of the training data. The correct procedure here would be to convert this into the range of [0, 1] or [-1, 1].
The reason that the [0, 255] range does not work as well is due to the fact that the second hidden layer of neurons will receive really positive or negative inputs.
When the backpropagation algorithm computes the gradient, the change computed for each weight will be really small as it is proportional to the slope of the activation function at the input to the neuron (the derivative of the logistic function is exp(-x)/(1+exp(-x)), which is close to 0 for really positive and negative values of x). Thus, the neural network will take really long to train and, in my case, was not able to learn the data well.
With the correct method, I am able to achieve around 90% accuracy for a 784*200*10 neural network in a fairly short time, though it still is not nearly as accurate as what the author says he is able to achieve using an even simpler algorinthm in the link mentioned in the question.

Related

Pushing objects back and forth between arrays results in missing objects

I have several JSON files with fake users.
They look like this:
{"name":"Beau Evans","personalityType":"yellow","skills":"JavaScript"}.
They are all pushed into an array called 'people'.
Now what I wish to do is to sort them all into subgroups into const groups = []; array.
The requirement for the groups is that they all need to share the same personalityType. (blue, yellow, red, or green) and they all need to differ in skills.
So one with HTML, JavaScript, or CSS.
And this of course resulted in some groups being of just 1 user. So I wanted to extract those back into a remainingPeople array, and then add the remainingPeople EVENLY to groups that meet the requirements so maybe 1 yellowCSS, 1 yellowJavaScript, 1 yellowHTML. It didn't matter if it turned out to be maybe 2 yellowHTML.
This is the code that I've written:
Which resulted into 2 problems.
The while loop on the bottom never stopped looping and crashed the site depending on how many JSON files with fake users I had!
And problem 2: Some users got erased out of existence so I ended up with fewer people in the groups' array than I had in the people array.
Why is this?
let homogenousGroups = [];
for (let i = 0; i < Math.floor(people.length / 3); i++) {
homogenousGroups.push([{
group: i
}]);
}
let groupsCreator = () => {
// this is to add people that has the same personality and different skills to the same group
let addPersonSameColor = (group) => {
people.sort(() => Math.random() - 0.5);
for (let j = 0; j < people.length; j++) {
let person = people[j];
let hasPersonality = group.some(groupPerson => groupPerson.personalityType === person.personalityType);
let hasSkills = group.some(groupPerson => groupPerson.skills === person.skills);
if (group.length === 0) {
group.push(person);
people.splice(j, 1);
j--;
} else if (hasPersonality && !hasSkills) {
group.push(person);
people.splice(j, 1);
j--;
}
}
};
// this runs the function above for each person in
for (let x = 0; x < homogenousGroups.length; x++) {
addPersonSameColor(homogenousGroups[x]);
}
// this will remove any object that does not have the name property
for (let x = 0; x < homogenousGroups.length; x++) {
for (let y = 0; y < homogenousGroups[x].length; y++) {
if (!homogenousGroups[x][y].name) {
homogenousGroups[x].splice(y, 1);
y--;
}
}
}
// this is to push any group that has less than 3 people back to the people array
for (let x = 0; x < homogenousGroups.length; x++) {
if (homogenousGroups[x].length <= 2) {
let removed = homogenousGroups[x].splice(0, homogenousGroups[x].length);
people2.push(...removed);
}
for (let x = 0; x < people.length; x++) {
if (people[x].group) {
people.splice(x, 1);
x--;
}
}
}
// this is to remove any empty arrays in my group array
for (let x = 0; x < homogenousGroups.length; x++) {
if (homogenousGroups[x].length === 0) {
homogenousGroups.splice(x, 1);
x--;
}
}
while (people.length > 1) {
for (let i = 0; i < homogenousGroups.length; i++) {
for (let j = 0; j < people.length; j++) {
if (people[j].personalityType === homogenousGroups[i][0].personalityType) {
homogenousGroups[i].push(people[j]);
people.splice(j, 1);
j--;
break;
}
}
}
}
};

Find max sum submatrix in 2D array/matrix

Please find my current implementation below:
function findMaxSumSubMatrix(matrix) {
var dim = matrix[0].length;
// initialize prefix sum matrix
var ps = new Array();
for (var _ = 0; _ < dim; _++) {
ps[_] = new Array();
}
// calculate vertical prefix sum matrix
for (var i = 0; i < dim; i++) {
for (var j = 0; j < dim; j++) {
if (j == 0) {
ps[j][i] = matrix[j][i];
} else {
ps[j][i] = matrix[j][i] + ps[j - 1][i];
}
}
}
// console.log(ps); // log prefix sum matrix
var maxSum = 0;
var min, temp;
// using the prefix sum matrix, iterate over all combinations and keep track of the max (Kadane's algorithm)
for (var i = 0; i < dim; i++) {
for (var j = i; j < dim; j++) {
min = 0;
temp = 0;
for (var k = 0; k < dim; k++) {
if (i == 0) {
temp += ps[j][k];
} else {
temp += ps[j][k] - ps[i - 1][k];
}
if (temp < min) {
min = temp;
}
if (temp - min > maxSum) {
maxSum = temp - min;
}
}
}
}
return maxSum;
}
var example1 = [
[1, -61, 5126, 612, 6],
[41, 6, 7, 2, -7],
[1, 73, -62, 678, 1],
[7, -616136, 61, -83, 724],
[-151, 6247, 872, 2517, 8135],
];
console.log(findMaxSumSubMatrix(example1)); // expected output: 18589
This works as expected, the output is correct.
However, I didn't write the code myself entirely.
What is unclear to me is the "min" and this part:
if (temp < min) {
min = temp;
}
if (temp - min > maxSum) {
maxSum = temp - min;
}
Can someone explain to me what's happening there, and why it's needed? I tried omitting it, giving incorrect results.
Thank you.
Think of this as a simple 1D array, where you have to find the maximum contiguous subsequence sum (exactly what Kadane's Algorithm does). For each prefix sum, you'll consider the lowest prefix sum that precedes it and calculate the difference (picking the lowest because you need to maximise the difference).
Similarly, the 2D array here also stores the prefix sum. We use min to keep a track of the lowest sum encountered in the current column. Since we need the maximum sum, we try to maximise the difference between current prefix sum (that is temp) and the minimum sum encountered (that is min).

Largest Triple Products without using sort?

I implemented the Largest Triple Products algorithm, but I use sort which makes my time complexity O(nlogn). Is there a way to implement it without a temporary sorted array?
The problem:
You're given a list of n integers arr[0..(n-1)]. You must compute a list output[0..(n-1)] such that, for each index i (between 0 and n-1, inclusive), output[i] is equal to the product of the three largest elements out of arr[0..i] (or equal to -1 if i < 2, as arr[0..i] then includes fewer than three elements).
Note that the three largest elements used to form any product may have the same values as one another, but they must be at different indices in arr.
Example:
var arr_2 = [2, 4, 7, 1, 5, 3];
var expected_2 = [-1, -1, 56, 56, 140, 140];
My solution:
function findMaxProduct(arr) {
// Write your code here
if(!arr || arr.length === 0) return [];
let helper = arr.slice();
helper.sort((a,b)=>a-b); // THIS IS THE SORT
let ans = [];
let prod = 1;
for(let i=0; i<arr.length; i++) {
if(i < 2) {
prod *= arr[i];
ans.push(-1);
}
else {
if(i === 3) {
prod *= arr[i];
ans.push(prod);
} else if(arr[i] < helper[0]) {
ans.push(prod);
} else {
const min = helper.shift();
prod /= min;
prod *= arr[i];
ans.push(prod);
}
}
}
return ans;
}
Thanks
You don't need to sort it. You just maintain an array of the largest three elements at each index.
For the first three elements it is simple you just assign the product of them to the third element in the result.
For the next elements, you add the current element to the three-largest-element-array and sort it and take the elements from 1 to 3 ( the largest three ) and assign the product of those at that index in result array. Then update the three-element-array with largest three.
Complexity :
This sort and slice of three-element-array should be O(1) because each time atmost 4 elements are there in the array.
Overall complexity is O(n).
You can do it as follows :
function findMaxProduct(arr) {
if(!arr) return [];
if (arr.length < 3) return arr.slice().fill(-1)
let t = arr.slice(0,3)
let ans = arr.slice().fill(-1,0,2) //fill first two with -1
ans[2] = t[0]*t[1]*t[2];
for(let i=3; i<arr.length; i++) {
t.push(arr[i]);
t = t.sort().slice(1,4);
ans[i] = t[0]*t[1]*t[2];
}
return ans;
}
I am keeping the array ordered (manually). Then just get the first 3 elements.
function findMaxProduct(arr) {
let results = [];
let heap = [];
for (let i = 0; i < arr.length; i++) {
// Insert the new element in the correct position
for (let j = 0; j < heap.length; j++) {
if (arr[i] >= heap[j]) {
heap.splice(j, 0, arr[i]);
break;
}
}
// No position found, insert at the end
if (heap.length != i + 1) {
heap.push(arr[i]);
}
if (i < 2) {
results.push(-1);
} else {
results.push(heap[0] * heap[1] * heap[2]);
}
}
return results;
}
You can make an array that holds three currently largest integers, and update that array as you passing through original array. That's how you will always have three currently largest numbers and you will be able to solve this with O(n) time complexity.
I think there's a faster and more efficient way to go about this. This is a similar thought process as #Q2Learn, using Python; just faster:
def findMaxProduct(arr):
#create a copy of arr
solution = arr.copy()
# make first 2 elements -1
for i in range(0,2):
solution[i] = -1
#for each item in copy starting from index 2, multiply item from 2 indices b'4 (notice how each index of arr being multiplied is reduced by 2, 1 and then 0, to accommodate each move)
for i in range(2, len(arr)):
solution[i] = arr[i-2] * arr[i-1] * arr[i]
return solution
check = findMaxProduct(arr)
print(check)
Single Scan Algorithm O(n)
We don't need to necessarily sort the given array to find the maximum product. Instead, we can only find the three largest values (x, y, z) in the given stage of iteration:
JavaScript:
function findMaxProduct(arr) {
let reults = []
let x = 0
let y = 0
let z = 0
for(let i=0; i<arr.length; i++) {
n = arr[i]
if (n > x) {
z = y
y = x
x = n
}
if (n < x && n > y) {
z = y
y = n
}
if (n < y && n > z) {
z = n
}
ans = x*y*z
if (ans === 0) {
results.push(-1)
} else {
results.push(ans)
}
return ans;
}
Python:
def findMaxProduct(arr):
results = []
if not arr:
return []
x = 0
y = 0
z = 0
for i, n in enumerate(arr):
if n > x:
z = y
y = x
x = n
if n < x and n > y:
z = y
y = n
if n < y and n > z:
z = n
ans = x*y*z
if ans == 0:
results.append(-1)
else:
results.append(ans)
print(results)
public int[] LargestTripleProducts(int[] input)
{
var ansArr = new int[input.Length];
var firstLargetst = input[0];
var secondLargetst = input[1];
ansArr[0] = ansArr[1] = -1;
for (int i = 2; i < input.Length; i++)
{
ansArr[i] = firstLargetst * secondLargetst * input[i];
if (firstLargetst < input[i] && firstLargetst < secondLargetst)
{
firstLargetst= input[i];
continue;
}
if (secondLargetst < input[i] && secondLargetst < firstLargetst)
{
secondLargetst= input[i];
}
}
return ansArr;
}
Python solution based on #SomeDude answer above. See explanation there.
def findMaxProduct(arr):
if not arr:
return None
if len(arr) < 3:
for i in range(len(arr)):
arr[i] = -1
return arr
three_largest_elem = arr[0:3]
answer = arr.copy()
for i in range(0, 2):
answer[i] = -1
answer[2] = three_largest_elem[0] * three_largest_elem[1] * three_largest_elem[2]
for i in range(3, len(arr)):
three_largest_elem.append(arr[i])
three_largest_elem = sorted(three_largest_elem)
three_largest_elem = three_largest_elem[1:4]
answer[i] = three_largest_elem[0] * three_largest_elem[1] * three_largest_elem[2]
return answer #Time: O(1) n <= 4, to Overall O(n) | Space: O(1)
Python has it's in-built package heapq, look at it for it.
Credit: Martin
> Helper function for any type of calculations
import math
> Heap algorithm
import heapq
> Create empty list to append output values
output = []
def findMaxProduct(arr):
out = []
h = []
for e in arr:
heapq.heappush(h, e)
if len(h) < 3:
out.append(-1)
else:
if len(h) > 3:
heapq.heappop(h)
out.append(h[0] * h[1] * h[2])
return out
Hope this helps!

Break-Point Implementation for Fixed-Point Iteration for System of Equations in Javascript

const x = new Array(3).fill(0)
const x0 = new Array(3).fill(0)
const er = new Array(3).fill(0)
const C = [1, 1, 1];
for (let j = 0; j < 1000; j++) {
for (let i = 0; i < C.length; i++) {
x[i] = C[i] + 1 / x0[i];
er[i] = Math.abs(x0[i] - x[i])/x0[i];
x0[i] = x[i];
if (er[i] < 0.0001){
break;
}
}
}
console.log("x", x, "er", er)
My goal is to solve for x, a 1D array, using fixed-point iteration method and insert a break point when each solution converges within 0.0001 tolerance error. Unfortunately, when the first element reaches the desired convergence error limit, it breaks the loop while other solutions are yet to reach.
Is there a better way to implement the break in this case? If I do not include the break and the solutions are displayed below (please note that I have set the parameter C to have the same value so as to better see the crux of this problem).
const x = new Array(3).fill(0)
const x0 = new Array(3).fill(0)
const er = new Array(3).fill(0)
const C = [1, 1, 1];
for (let j = 0; j < 1000; j++) {
for (let i = 0; i < C.length; i++) {
x[i] = C[i] + 1 / x0[i];
er[i] = Math.abs(x0[i] - x[i])/x0[i];
x0[i] = x[i];
}
}
console.log("x", x, "er", er)

Is there a way to improve this code in order to avoid a timeout with large arrays?

I am working with this problem: https://www.hackerrank.com/challenges/fraudulent-activity-notifications/
My code works almost fine, but for some test cases it fails, because of the large array (over 200000 items). I am spending hours trying to understand what I can do to improve the speed, but I cannot come out with a working solution, so 2 of my tests always fail for timeout and I am frustrated trying to pass this test.
I think I cannot avoid the first loop and also the loop in sort, but cannot think of a faster way.
The problem described in the website is is this:
HackerLand National Bank has a simple policy for warning clients about possible fraudulent account activity. If the amount spent by a client on a particular day is greater than or equal to the client's median spending for a trailing number of days, they send the client a notification about potential fraud. The bank doesn't send the client any notifications until they have at least that trailing number of prior days' transaction data.
I solved it with this code
function getMedianNumber(arr) {
arr.sort((a, b) => a - b);
let medianNumber = 0;
const middle = Math.floor(arr.length / 2);
if (arr.length % 2 === 0) {
// Is even we get the median number
medianNumber = (arr[middle] + arr[middle - 1]) / 2;
} else {
const index = Math.floor(middle);
medianNumber = arr[index];
}
return medianNumber;
}
function activityNotifications(expenditure, d) {
let notifications = 0;
let len = expenditure.length - 1;
for (let i = len; i > d - 1; i--) {
let trailingDays = expenditure.slice(i - d, i);
let dayExpense = expenditure[i];
let median = getMedianNumber(trailingDays);
if (expenditure[i] >= median * 2) {
notifications++;
}
}
return notifications;
}
It only fails in 2 test cases because the passed array is huge and I get a timeout error.
expenditure.slice(i - d, i); is too expensive, you are making it O(n^2) by copying the array elements over each iteration. Use indexes over the original array to calculate median: getMedianNumber(arr, startIndex, endIndex).
function copy(a, ind) {
b = [];
for(var i = ind; i < a.length; ++i) {
b.push(a[i]);
}
return b;
}
function processData(input) {
//Enter your code here
var inputArr = input.split("\n");
var d = parseInt(inputArr[0].split(" ")[1]);
var arr = inputArr[1].split(" ").map(Number);
var countArray = [], sortedArray = [], tempArray = [], notifications = 0, median, count, middle;
for(var i = 0; i <= 200; ++i) {
countArray.push(0);
}
for(i = 0; i < d; ++i) {
countArray[arr[i]]++;
}
for(var j = 0; i < arr.length; ++i, ++j) {
tempArray = [], count = 0;
for(var k = 0; k <= 200; ++k) {
if(countArray[k] > 0) {
count += countArray[k];
tempArray.push({
no: k,
count: count
});
}
}
middle = {};
if((d&1) === 0) {
middle.index = count / 2;
} else {
middle.index = Math.ceil(count / 2);
}
var tempCount = 0;
for(k = 0; k < tempArray.length; ++k) {
if(tempArray[k].count === middle.index) {
if((d&1) === 0) {
median = (tempArray[k].no + tempArray[k + 1].no) / 2;
break;
} else {
median = tempArray[k].no;
break;
}
} else if(tempArray[k].count > middle.index) {
median = tempArray[k].no;
break;
}
}
//console.log(tempArray, median, arr[i]);
if(arr[i] >= (2 * median)) {
notifications++;
}
countArray[arr[i]]++;
countArray[arr[j]]--;
}
console.log(notifications);
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function (input) {
_input += input;
});
process.stdin.on("end", function () {
processData(_input);
});

Categories

Resources