Splitting of array - javascript

Given a non-empty array, if there is a place to split the array so that the sum of the numbers on one side is equal to the sum of the numbers on the other side return the length of the two arrays as an array but if there is no place to split the array, return -1
canBalance([1, 1, 1, 2, 1]) → [3,2]
canBalance([2, 1, 1, 2, 1]) → -1
canBalance([10, 10]) → [1,1]
function canBalance(array) {
//Type your solutions here
}
module.exports = canBalance;

Make two variables, and add and subtract each item in the array until they are equal.
function canBalance(array) {
let start = 0, end = array.reduce((a, c) => a + c, 0);
for (let i = 0; i < array.length; i++) {
start += array[i];
end -= array[i];
if (start == end) {
return [i + 1, array.length - (i + 1)];
}
}
return -1;
}
console.log(canBalance([1, 1, 1, 2, 1]));
console.log(canBalance([2, 1, 1, 2, 1]));
console.log(canBalance([10, 10]));

loop through the array from the first (index 0) to the one before the last (length -1) since you want to check only until the second last to compare against the last one.
you can use slice to get the array minus the one element being iterated each time and use a reducer to get the sum
const reducer = (a, c) => a+c;
function canBalance(array) {
var result = [];
var arr = [];
for(var i=0; i<array.length - 1; i++){
arr.push(array[i]);
var leftover = array.slice(i+1,array.length);
if(arr.reduce(reducer) === leftover.reduce(reducer)){
result.push(arr.length);
result.push(leftover.length);
}
}
return result.length > 0 ? result : -1;
}

Related

Given a list of n integers arr[0..(n-1)], determine the number of different pairs of elements within it which sum to k

I'm tackling this problem and I can't seem to arrive at the correct solution. The question is:
"Given a list of n integers arr[0..(n-1)], determine the number of different pairs of elements within it which sum to k. If an integer appears in the list multiple times, each copy is considered to be different; that is, two pairs are considered different if one pair includes at least one array index which the other doesn't, even if they include the same values.
My approach is that I'm building a map that contains each number in the array and the number of times it occurs. Then I iterate over the map to find my answer.
function numberOfWays(arr, k) {
let output = 0;
let map = {};
// put values and # of occurences into map
for(let i = 0; i < arr.length; i++) {
let key = arr[i];
if(!(key in map)) {
map[key] = 1;
} else {
map[key]++;
}
}
for(let key in map) {
let difference = k-key
if((difference) in map) {
if(k/2 === key) {
output += map[key]*(map[key]-1)/2;
} else {
output += map[key] * map[key] / 2; // divide by 2 so that pairs aren't counted twice
}
}
}
return output;
}
The two test cases are:
var arr_1 = [1, 2, 3, 4, 3]; expected result: [2] -- I'm getting [3]
var arr_2 = [1, 5, 3, 3, 3]; expected result: [4] -- I'm getting [5.5]
I'm definitely doing something wrong in my calculations, but I can't seem to wrap my ahead around it.
This is one way to nest the loops to find the pairs in array "arr" with the sum "k".
function numberOfWays(arr, k) {
let output = 0;
for (i = 0; i < arr.length; i++) {
for (n = i+1; n < arr.length; n++) {
if (arr[i] + arr[n] == k)
output++;
}
}
return output;
}
You could count the smaller and greater values for building k and then taker either the product or if only two of the same value is building the sum take factorial of the cound divided by two.
function numberOfWays(array, k) {
const
f = n => +!n || n * f(n - 1),
pairs = {};
for (const value of array) {
const smaller = Math.min(value, k - value);
pairs[smaller] ??= { one: 2 * smaller === k, min: 0, max: 0 };
pairs[smaller][value === smaller ? 'min' : 'max']++;
}
let count = 0;
for (const k in pairs) {
const { one, min, max } = pairs[k];
if (one) {
if (min > 1) count += f(min) / 2;
} else if (min && max) {
count += min * max;
}
}
return count;
}
console.log(numberOfWays([1, 2, 3, 4, 3], 6)); // 2
console.log(numberOfWays([1, 5, 3, 3, 3], 6)); // 4
function numberOfWays(items, k) {
// Clone as to not mutate original array
const arr = [...items]
let count = 0
// Stop comparing when no items left to compare
while (arr.length) {
for (let i = 0; i < arr.length; i++) {
// Compare each item to the first item
const sum = arr[0] + arr[i + 1]
if (sum === k) {
count++
}
}
// Remove the first item after comparing to the others
arr.shift()
}
return count
}
console.log(numberOfWays([1, 2, 3, 4, 3], 6))
console.log(numberOfWays([1, 5, 3, 3, 3], 6))
console.log(numberOfWays([1, 1, 1, 1, 1], 2))
import math
from math import factorial as f
def get_number_of_combination(n,r):
return f(n)//(f(n-r)*f(r))
def numberOfWays(arr, k):
num_count = {}
num_ways = 0
for i in arr:
old_count = num_count.get(i,0)
num_count.update({i: old_count+1})
for i in list(num_count.keys()):
if i == k - i and num_count.get(i,0) > 1:
num_ways += (get_number_of_combination(num_count.get(i,0),2))
num_count.update({i:0})
else:
i_n = num_count.get(i, 0)
ki_n = num_count.get(k-i, 0)
num_ways += i_n * ki_n
num_count.update({i:0,k-i:0})
return num_ways

Splitting array into equal halves

Problem: find an index N where the sum of the integers to the left of N is equal to the sum of the integers to the right of N. If there is no index that would make this happen, return -1.
My solution
function findEvenIndex(arr) {
var sum = i => i.reduce((a, b) => a + b),
l = arr.length;
for (let j = 0; j <= l; j++) {
if (sum(arr.slice(0, j - 1)) === sum(arr.slice(j, l))) {
return j
} else {
continue;
}
}
return -1
}
console.log(
findEvenIndex([1, 2, 3, 4, 3, 2, 1])
)
When I run this on say findEvenIndex([1,2,3,4,3,2,1]), It doesn't return anything? Where is the error that prevents 3 from being returned in the case of this example?
I've set the for loop procedure as follows to see what's going on
for(let j = 0; j <= arr.length; j++){
var left = arr.slice(0, j-1), right = arr.slice(j)
console.log(left, right)
}
/* returns
[1] [3,4,3,2,1]
[1,2] [4,3,2,1]
[1,2,3] [3,2,1]
as expected
*/
However, when try to console.log the sum of these arrays:
function sum(i){ return i.reduce((a, b) => a+b)}
var l = arr.length;
for(let j = 0; j <= l; j++){
var left = arr.slice(0, j-1), right = arr.slice(j)
console.log(sum(left), sum(right))
}
Using the snippet above, findEvenIndex([1,2,3,4,3,2,1]) returns "15 16"?
The main issue with your code is that calling sum([]) throws an error (which you will find in the console during debugging):
Reduce of empty array with no initial value
The reduce method does not know what to return if your array doesn't have any values. You solve it by passing the initial value as a second argument to .reduce:
const add = (a, b) => a + b;
[1, 2, 3].reduce(add); // add(add(1, 2), 3)
[1, 2].reduce(add); // add(1, 2)
[1].reduce(add); // 1
[].reduce(add); // ERROR: Reduce of empty array
// with no initial value
[1, 2].reduce(add, 0); // add(add(0, 1), 2)
[1].reduce(add, 0); // add(0, 1)
[].reduce(add, 0); // 0
Once you fix that, it's easier to debug the rest of the code.
Fixing it
Here's an example that I think does what it should do:
function findEvenIndex(arr) {
// Add a seed value --v
var sum = i => i.reduce((a, b) => a + b, 0),
l = arr.length;
for (let j = 0; j <= l; j++) {
const left = arr.slice(0, j);
const right = arr.slice(j + 1);
const leftSum = sum(left);
const rightSum = sum(right);
console.log(
{ left, right, leftSum, rightSum }
);
if (leftSum === rightSum) {
return j
}
}
return -1
}
console.log(
findEvenIndex([1]), // 0
findEvenIndex([1, 2, 3, 4, 3, 2, 1]), // 3
findEvenIndex([10, 0, 5, 5]), // 1
findEvenIndex([3, 2, 1]) // -1
)
Another approach
Note that looping over all elements of the array for every index is quite expensive! A more efficient approach would be:
Take the sum of the source array, store it as rightSum
Define leftSum as 0
Look at the integer value at index 0 and subtract it from rightSum
If leftSum === rightSum, return 0
Else, add value to leftSum and increment index
Once you've reached the final index, return -1
const findEvenIndex = (arr) => {
let leftSum = 0;
let rightSum = arr
.reduce((a, b) => a + b, 0);
for (let i = 0; i < arr.length; i += 1) {
const n = arr[i];
rightSum -= n;
if (leftSum === rightSum) return i;
leftSum += n;
}
return -1;
}
console.log(
findEvenIndex([1]), // 0
findEvenIndex([1, 2, 3, 4, 3, 2, 1]), // 3
findEvenIndex([10, 0, 5, 5]), // 1
findEvenIndex([3, 2, 1]) // -1
)
You can get the index like following using reduce(). Your implementation regarding reduce() is not correct.
function findEvenIndex(arr)
{
for(let i = 0; i < arr.length; i++) {
let leftSum = arr.slice(0, i).reduce((accumulator, current) => accumulator + current, 0);
let rightSum = arr.slice(i + 1).reduce((accumulator, current) => accumulator + current, 0);
if (leftSum === rightSum) {
return i;
}
}
return -1;
}
console.log(
findEvenIndex([1, 2, 3, 4, 3, 2, 1])
)
Please check following blog to find out how Array reduce() work
https://www.javascripttutorial.net/javascript-array-reduce/
Upon finishing my solution, I noticed that it's effectively the same as #Abu's answer above. The idea is to brute force the way through the array, comparing the two halves as you go.
/*
Find an index N where the sum of the integers to the left of N is equal to the sum of the integers to the right of N. If there is no index that would make this happen, return -1
*/
const array = [10, 90, 10, 1, 10, 90, 10];
// incrementTotal :: (Number t, Number n) -> t
incrementTotal = (total, number) => total + number;
// indexIsEqual :: (Array a, Number c) -> Boolean
function indexIsEqual(array, count) {
let chunkL = array.slice(0, count-1);
let chunkR = array.slice(count , );
return chunkL.reduce(incrementTotal) === chunkR.reduce(incrementTotal);
}
// findEvenIndex :: (Array a) -> (a[x] || -1)
function findEvenIndex(array) {
for (let count = 2; count < array.length; count++) {
if (indexIsEqual(array, count)) {
return array[count-1];
}
}
return -1;
}
console.log(findEvenIndex(array));

Find Missing Numbers from Unsorted Array

I found this JavaScript algorithm excercise:
Question:
From a unsorted array of numbers 1 to 100 excluding one number, how will you find that number?
The solution the author gives is:
function missingNumber(arr) {
var n = arr.length + 1,
sum = 0,
expectedSum = n * (n + 1) / 2;
for (var i = 0, len = arr.length; i < len; i++) {
sum += arr[i];
}
return expectedSum - sum;
}
I wanted to try and make it so you can find multiple missing numbers.
My solution:
var someArr = [2, 5, 3, 1, 4, 7, 10, 15]
function findMissingNumbers(arr) {
var missingNumbersCount;
var missingNumbers = [];
arr.sort(function(a, b) {
return a - b;
})
for(var i = 0; i < arr.length; i++) {
if(arr[i+1] - arr[i] != 1 && arr[i+1] != undefined) {
missingNumbersCount = arr[i+1] - arr[i] - 1;
for(j = 1; j <= missingNumbersCount; j++) {
missingNumbers.push(arr[i] + j)
}
}
}
return missingNumbers
}
findMissingNumbers(someArr) // [6, 8, 9, 11, 12, 13, 14]
Is there a better way to do this? It has to be JavaScript, since that's what I'm practicing.
You could use a sparse array with 1-values at indexes that correspond to values in the input array. Then you could create yet another array with all numbers (with same length as the sparse array), and retain only those values that correspond to an index with a 1-value in the sparse array.
This will run in O(n) time:
function findMissingNumbers(arr) {
// Create sparse array with a 1 at each index equal to a value in the input.
var sparse = arr.reduce((sparse, i) => (sparse[i]=1,sparse), []);
// Create array 0..highest number, and retain only those values for which
// the sparse array has nothing at that index (and eliminate the 0 value).
return [...sparse.keys()].filter(i => i && !sparse[i]);
}
var someArr = [2, 5, 3, 1, 4, 7, 10, 15]
var result = findMissingNumbers(someArr);
console.log(result);
NB: this requires EcmaScript2015 support.
The simplest solution to this problem
miss = (arr) => {
let missArr=[];
let l = Math.max(...arr);
let startsWithZero = arr.indexOf(0) > -1 ? 0 : 1;
for(i = startsWithZero; i < l; i++) {
if(arr.indexOf(i) < 0) {
missArr.push(i);
}
}
return missArr;
}
miss([3,4,1,2,6,8,12]);
Something like this will do what you want.
var X = [2, 5, 3, 1, 4, 7, 10, 15]; // Array of numbers
var N = Array.from(Array(Math.max.apply(Math, X)).keys()); //Generate number array using the largest int from X
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;}); //Return the difference
};
console.log(N.diff(X));
Option 1:
1. create a binary array
2. iterate over input array and for each element mark binary array true.
3. iterate over binary array and find out numbers of false.
Time complexity = O(N)
Space complexity = N
Option 2:
Sort input array O(nLogn)
iterate over sorted array and identify missing number a[i+1]-a[i] > 0
O(n)
total time complexity = O(nlogn) + O(n)
I think the best way to do this without any iterations for a single missing number would be to just use the sum approach.
const arr=[1-100];
let total=n*(n+1)/2;
let totalarray=array.reduce((t,i)=>t+i);
console.log(total-totalarray);
You can try this:
let missingNum= (n) => {
return n
.sort((a, b) => a - b)
.reduce((r, v, i, a) =>
(l => r.concat(Array.from({ length: v - l - 1 }, _ => ++l)))(a[i - 1]),
[]
)
}
console.log(missingNum([1,2,3,4,10]));
Solution to find missing numbers from unsorted array or array containing duplicate values.
Array.prototype.max = function() {
return Math.max.apply(null, this);
};
var array1 = [1, 3, 4, 7, 9];
var n = array1.length;
var totalElements = array1.max(); // Total count including missing numbers. Can use max
var d = new Uint8Array(totalElements)
for(let i=0; i<n; i++){
d[array1[i]-1] = 1;
}
var outputArray = [];
for(let i=0; i<totalElements; i++) {
if(d[i] == 0) {
outputArray.push(i+1)
}
}
console.log(outputArray.toString());
My solution uses the same logic as trincot's answer
The time complexity is O(n)
const check_miss = (n) => {
let temp = Array(Math.max(...n)).fill(0);
n.forEach((item) => (temp[item] = 1));
const missing_items = temp
.map((item, index) => (item === 0 ? index : -1))
.filter((item) => item !== -1);
console.log(missing_items);
};
n = [5, 4, 2, 1, 10, 20, 0];
check_miss(n);

How to convert an array in an complex array

I have this array [2, 1, 2, 1, 1, 1, 1, 1]
I want if the sum of the values exceed four, it's make a new array in array.
I want a result like that: [[2,1],[2,1,1],[1,1,1]]
You could use Array#reduce and use it for adding the values of the last inserted array and for the whole result array.
The main part of the algorithm is this line
!i || r[r.length - 1].reduce(add, 0) + a > 4 ?
r.push([a]) :
r[r.length - 1].push(a);
In it, a check takes place, if i is zero (at start) or if the sum of the last array of the result is in sum with the actual item greater than 4, then a new array with the actual value is added. If not, then the element is pushed to the last array.
var data = [2, 1, 2, 1, 1, 1, 1, 1],
add = function (a, b) { return a + b; },
result = data.reduce(function (r, a, i) {
!i || r[r.length - 1].reduce(add, 0) + a > 4 ? r.push([a]) : r[r.length - 1].push(a);
return r;
}, []);
console.log(result);
You can loop through the array and build a new one, if the sum exceed 4 push the previous array into the result like:
var myArr = [2, 1, 2, 1, 1, 1, 1, 1];
var newArr = [];
var newInner = [];
for (var i = 0; i < myArr.length; i++) {
if (summArr(newInner) + myArr[i] > 4) {
newArr.push(newInner);
newInner = [];
}
newInner.push(myArr[i]);
if (i==myArr.length-1) newArr.push(newInner);
}
function summArr(arr) {
return arr.reduce(add, 0);
function add(a, b) {
return a + b;
}
}
Demo: https://jsfiddle.net/q0ps7960/
for simple way...
var array1 = [2, 1, 2, 1, 1, 1, 1, 1];
var tmp=[];
var output=[];
var sum=0;
for(var i=0; i<array1.length; i++){
sum +=array1[i];
if(sum<=4){
tmp.push(array1[i]);
}else{
output.push(tmp);
sum =array1[i];
tmp=[array1[i]];
}
}
output.push(tmp);
console.log(output);

Find the lowest unused number in an array using Javascript

I have an array full of numbers. Here's an example:
myArray = [0,1,2,4,5];
I need to find the lowest unused number starting from 1, so in this case it will be 3.
I've been reading up of using indexOf but I'm unsure how to use it for my specific purpose.
Assuming the array isn't sorted, you always start at 0, and taking into account your desire to find a highest number if there isn't one missing:
var k = [6, 0, 1, 2, 4, 5];
k.sort(function(a, b) { return a-b; }); // To sort by numeric
var lowest = -1;
for (i = 0; i < k.length; ++i) {
if (k[i] != i) {
lowest = i;
break;
}
}
if (lowest == -1) {
lowest = k[k.length - 1] + 1;
}
console.log("Lowest = " + lowest);
Logs answer 3. If 3 was also in there, would log 7 since no other number is missing.
If you aren't always starting at zero, use an offset:
var k = [6, 2, 3, 4, 5];
k.sort(function(a, b) { return a-b; }); // To sort by numeric
var offset = k[0];
var lowest = -1;
for (i = 0; i < k.length; ++i) {
if (k[i] != offset) {
lowest = offset;
break;
}
++offset;
}
if (lowest == -1) {
lowest = k[k.length - 1] + 1;
}
console.log("Lowest = " + lowest);
Logs answer 7 since none are missing after 2 which starts the sequence.
This takes a sequence starting from a number (like 1 in your example) and returns the lowest unused number in the sequence.
function lowestUnusedNumber(sequence, startingFrom) {
const arr = sequence.slice(0);
arr.sort((a, b) => a - b);
return arr.reduce((lowest, num, i) => {
const seqIndex = i + startingFrom;
return num !== seqIndex && seqIndex < lowest ? seqIndex : lowest
}, arr.length + startingFrom);
}
Example:
> lowestUnusedNumber([], 1)
1
> lowestUnusedNumber([1,2,4], 1)
3
> lowestUnusedNumber([3], 1)
1
In exchange for readability, it's slightly less optimized than the other example because it loops over all items in the array instead of breaking as soon as it finds the missing item.

Categories

Resources