Javascript Smallest Number in 3 Arrays - javascript

I can figure out iterating through an array for similar numbers, but creating a function in order to do so through 3 arrays is stumping me for some reason. For the assignment I need to limit my built in functions to indexOf and .length.
For example:
var sample = [1,2,3,5,6], [2,3,4,5,6], [4,5,6,7,8]
function smallestCommonNumber(arr1, arr2, arr3){
}
I will need this function to iterate through the three ascending arrays and return the smallest of any pairs (must match all 3 arrays) and if not, return false. I know that using indexOf will return a specified item, but how would I use that for an unspecified array?

Assuming the arrays are sorted with ascending values as specified in the question.
Iterate each number in one of the arrays and check if it exists in both of the other arrays using indexOf, if not found it will return -1, here using ~ operator to shift -1 to 0 to get a falsy value.
Could just as well just check .indexOf(..) > -1.
function smallestCommonNumber(arr1, arr2, arr3){
for (const number of arr1) {
if (~arr2.indexOf(number) && ~arr3.indexOf(number)) {
return number;
}
}
return false;
}
console.log(smallestCommonNumber([1,2,3,5,6], [2,3,4,5,6], [4,5,6,7,8]));
For a version that finds the smallest number without ascending arrays:
function smallestCommonNumber(arr1, arr2, arr3){
let smallest = null;
for (const number of arr1) {
if (~arr2.indexOf(number) && ~arr3.indexOf(number)) {
smallest = number < smallest ? number : smallest ?? number;
}
}
return smallest ?? false;
}
console.log(smallestCommonNumber([6,5,3,2,1], [2,3,4,5,6], [4,5,6,7,8]));

If the 3 arrays are sorted in ascending order you can iterate over all 3 arrays from left to right using 3 pointers until you get a number that occurs in all 3 arrays, and just return that number since that will be guaranteed to be the smallest:
function smallestCommonNumber(arr1, arr2, arr3) {
let i = 0,
j = 0,
k = 0;
while (i < arr1.length && j < arr2.length && k < arr3.length) {
if (arr1[i] === arr2[j] && arr2[j] === arr3[k]) {
return arr1[i];
} else if (arr1[i] < arr2[j]) {
i++;
} else if (arr2[j] < arr3[k]) {
j++;
} else {
k++;
}
}
return false;
}
const a1 = [1, 2, 3, 5, 6];
const a2 = [2, 3, 4, 5, 6];
const a3 = [4, 5, 6, 7, 8];
// Assumes a1, a2, and a3 are sorted in ascending order
console.log(smallestCommonNumber(a1, a2, a3));
As requested by #kinduser in the comments here is a solution that works with unsorted arrays as well:
function smallestCommonNumber(arr1, arr2, arr3) {
const set1 = new Set(arr1);
const set2 = new Set(arr2);
const intersection1 = new Set([...set1].filter(n => set2.has(n)));
if (!intersection1.size) {
return false;
}
const set3 = new Set(arr3);
const intersection2 = new Set([...intersection1].filter(n => set3.has(n)));
return intersection2.size ? Math.min(...intersection2) : false;
}
const a1 = [1, 2, 3, 5, 6];
const a2 = [2, 5, 4, 3, 6];
const a3 = [4, 5, 6, 7, 8];
console.log(smallestCommonNumber(a1, a2, a3));

var sample1 = [1,2,3,5,6]
var sample2 = [2,3,4,5,6]
var sample3 = [4,5,6,7,8]
function smallestCommonNumber(...arrays){
const smallestsOfAllArrays = []
arrays.forEach(array => {
smallestsOfAllArrays.push(smallestOfOneArray(array))
})
return smallestOfOneArray(smallestsOfAllArrays)
}
function smallestOfOneArray(oneArray){
return oneArray.reduce((acm, value) => acm <= value ? acm : value)
}
console.log(smallestCommonNumber(sample1, sample2, sample3))
//1

Do like:
function inArray(value, array){
if(array.indexOf(value) === -1){
return false;
}
return true;
}
function least(){
let a = [...arguments], l = a.length, q = l-1, r = [];
for(let i=0,b; i<l; i++){
b = a[i];
for(let n=0,c,h; n<l; n++){
if(i !== n){
c = a[n]; h = [];
for(let v of c){
if(inArray(v, b))h.push(v);
}
if(h.length === q)r.push(...h);
}
}
}
return Math.min(...r);
}
const sample1 = [6,3,1,5,2], sample2 = [2,3,4,5,6], sample3 = [4,5,6,7,8];
console.log(least(sample1, sample2, sample3));

Related

Find unique number in unsorted array JavaScript

I have to find a unique number in unsorted array, but my function returns wrong number, I can't understand why.
Here is my code:
function findUniq(arr) {
let sorted = [...arr].sort();
if (sorted.length === 0) return 0;
// do magic
let num = 0;
for (let i = 1; i < sorted.length; i++) {
if (sorted[num] !== sorted[i]) {
num++;
sorted[num] = sorted[i];
}
}
return num + 1;
}
const testArray = [9, 7, 7, 9, 6, 6, 5, 5, 5];
console.log(findUniq(testArray));
if I invoke findUniq([9,7,7,6,6,5,5,5]) it gives 4. What do I do wrong? Thanks in advance. I forgot to mention I have to have just one for loop to implement O(n) time complexity
I don't know why your solution doesn't work, but here is working code:
const arr = [9,9,7,7,8,6,1,6,5,5,5]
function findUnique(arr){
const sorted = [...arr].sort()
if(sorted[0] !== sorted[1]) return sorted[0]
if(sorted[sorted.length - 1] !== sorted[sorted.length - 2]) return sorted[sorted.length - 1]
for(let i = 0; i < sorted.length; i++){
if(sorted[i] !== sorted[i - 1] && sorted[i] !== sorted[i + 1]) return sorted[i]
}
return "no unique"
}
console.log(findUnique(arr))
This should work:
It returns only one unique number in array or undefined
If you want all unique numbers replace return arr[0] with return arr. It will then return array of all unique numbers (or empty array if there are not any)
function findUniq(arr) {
arr.filter((item, index) => {
arr.splice(index, 1)
const unique = !arr.includes(item)
arr.splice(index, 0, item)
return unique
})
return arr[0]
}
ES6 aproach:
function findUniq(arr) {
return arr
.map((c) => arr.filter((b) => c == b))
.filter((e) => e.length < 2)
.reduce((total, cur) => total.concat(cur), [])
}
You can use reduce and can find the item that repeats once in the last index.
var arr = [9,7,7,6,6,5,5,5]
var uniqueNumber;
arr.reduce((obj,val,index) =>
{
obj[val] ? ++obj[val] : obj[val] = 1;
if(index == (arr.length - 1))
{
uniqueNumber = Object.keys(obj).find(key => obj[key] === 1)
}
return obj
},{})
console.log(uniqueNumber)
To do it in a single O(n) loop, reduce, keeping track of counts as well as a set of singular items.
function findUniq(arr) {
let [single] = arr.reduce((acc, el) => {
if (!acc[el]) acc[el] = 0;
if (++acc[el] === 1) acc.singular.add(el);
else acc.singular.delete(el);
return acc;
}, { singular: new Set() }).singular;
return single;
}
const input = [2, 2, 9, 7, 7, 6, 6, 5, 5, 5];
const result = findUniq(input);
console.log(result);

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

Dynamic nested loops over array

I'm trying to figure out how to dynamically doing a deep looping over an array.
Lets say i have a function that takes an array of numbers and a total number, it will loop over the array and will return a tuple of the numbers that together make the sum of the total:
const sumOfTwo = (arr, total) => {
let map = {};
for (let currentNum of arr) {
if (map[currentNum] !== undefined) {
return [map[currentNum], currentNum]
} else {
map[total - currentNum] = currentNum;
}
}
return [];
}
const num = 6
const arr = [4, 5, 2, 3, 1];
const result = sumOfTwo(arr, num);
console.log(result); // [4, 2]
Now if i want to create the same function but that finds a sum of three numbers, i will have to do a nested loop:
function sumOfThree(arr, total) {
for (let i = 0; i < arr.length; i++) {
let processed = {};
let firstNum = arr[i];
let firstDelta = total - firstNum;
for (let j = i + 1; j < arr.length; j++) {
let secondNum = arr[j];
let secondDelta = firstDelta - secondNum;
if (processed[secondDelta]) {
return [firstNum, secondNum, secondDelta];
}
processed[secondNum] = true;
}
}
return [];
}
const arr = [1, 2, 3, 4];
const sum = 6;
const result = sumOfThree(arr, sum);
console.log(result); // [1, 3, 2]
If i want a sumOfFour function, i guess i need another nested loop and so on.
What i actually want is to create a generic function sumOf that will take the array, the total but also that number of numbers it should add up to the total. I was thinking of doing a recursive flow but got stuck on the very first line, now i'm not so sure it can be done.
Any suggestion would be much appropriated
Generators are really useful then to yield values up, also you can pass down the previous sum and values through the recursion:
function* sumUp(values, target, n, previous = [], sum = 0) {
// Base case: if the combination of n values is target, yield it, or exit
if(n <= 0) {
if(sum === target) yield previous;
return;
}
// otherwise add this combo
for(const value of values) {
// don't use the same number twice
if(previous.includes(value)) continue;
yield* sumUp(values, target, n - 1, [...previous, value], sum + value);
}
}
Usable as:
// all combinations
console.log([...sumUp([1, 2, 3, 4], 7, 2)]);
// just the first
console.log(sumUp([1, 2, 3, 4], 7, 2).next().value);

How to find diff between array and array of arrays

x = [1, 2,3, 5]; y = [1, [2], [3, [[4]]],[5,6]]));
I have to find the difference between these 2 arrays.
function arr_diff (a1, a2) {
var a = [], diff = [];
for (var i = 0; i < a1.length; i++) {
a[a1[i]] = true;
}
for (var i = 0; i < a2.length; i++) {
if (a[a2[i]]) {
delete a[a2[i]];
} else {
a[a2[i]] = true;
}
}
for (var k in a) {
diff.push(k);
}
return diff;
};
This is what I tried but since it has array of arrays, this not working for me.
Can anyone please suggest help.
You could just flatten the arrays before you find the difference
function arr_diff(a1, a2) {
a1 = a1.toString().split(',');
a2 = a2.toString().split(',');
if (a1.length < a2.length) {var t = a1; a1 = a2; a2 = t};
return a1.filter( x => (!a2.includes(x)) ).map(Number);
}
var x = [1, 2,3, 5];
var y = [1, [2], [3, [[4]]],[5,6]];
var r = arr_diff(x,y);
console.log(r);
You definitely need to flatten all the arrays you want to compare using a function found here.
After flattening them, you can compare them using a function found here
let x = [1, 2,3, 5];
let y = [1, [2], [3, [[4]], [5,6] ]]
const flatten = list => list.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
)
const difference = (arr1,arr2) => {
arr1 = flatten(arr1)
arr2 = flatten(arr2)
return arr1.filter(e => arr2.indexOf(e) === -1)
.concat(arr2.filter(e => arr1.indexOf(e) === -1))
}
console.log(difference(x,y)) // [4,6]

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);

Categories

Resources