Suppose that an array of N numbers is given.
How to find a subset that its sum is multiple of N?
I want to know the best approach.
The recursive function would be the right choice, but stack overflow for large number N isn't allowed.
Here is my code, but it doesn't work.
const arr = [];
const TOTAL_NUM = 5;
let sum = 0;
for (let i = 0; i < TOTAL_NUM; i++) {
arr.push(parseInt(Math.random() * TOTAL_NUM) + 1);
sum += arr[i];
}
const mod = sum % TOTAL_NUM;
for (let i = 0; i < TOTAL_NUM; i++) {
let sum = arr[i]
let found = false;
for (let j = i + 1; j < TOTAL_NUM; j++) {
sum += arr[j];
if (sum % TOTAL_NUM === 0 || (sum - mod) % TOTAL_NUM === 0) {
found = true;
console.log('Sum = %d', sum);
break;
}
}
if (found) break;
}
We don't necessarily need to recurse. We can iterate on the known remainders so far.
JavaScript code below (this is exhaustive; we could have a more space efficient version to return just one subset by adjusting what we store):
// 'rem' stands for "remainder"
function f(A){
let N = A.length
let rems = {0: [[]]}
for (let a of A){
let newRems = {}
for (let rem in rems){
let newRem = (a + Number(rem)) % N
newRems[newRem] = (rems[newRem] || []).concat(
rems[rem].map(x => x.concat(a)))
}
newRems[a % N] = (rems[a % N] || []).concat([[a]])
rems = Object.assign(rems, newRems)
}
return rems[0].slice(1)
}
var A = [1, 6, 2, 3, 4]
console.log(JSON.stringify(A))
console.log(`N: ${A.length}`)
console.log(JSON.stringify(f(A)))
I want to answer my question and to be evaluated by audiences.
This is my current code. I'll explain.
Assume we have an array of N numbers.
In loop for variable i = 0, we get N subsets and its inner sums. If there is at least one subset that its sum is multiple of N, it will be a solution. If not, the value of (sum % N) would take one value between 1 and (N-1). There exist N sums and (N-1) possible remainders. Therefore, there exist at least one pair (n, m) that n-th sum and m-th sum would have the same remainder, where 0 < n < m < N.
In this case, the sum of a subset [arr[n+1], arr[n+2], ... arr[m]] would be the multiple of N. So we can find n and m to solve this problem.
Below is the code to find n and m.
const arr = [];
const TOTAL_NUM = 5;
for (let i = 0; i < TOTAL_NUM; i++) {
arr.push(parseInt(Math.random() * TOTAL_NUM * 10) + 1);
}
console.log(arr.join(', '));
// find n and m
for (let i = 0; i < TOTAL_NUM; i++) {
let sum = 0;
found = false;
for (let j = i; j < TOTAL_NUM; j++) {
sum += arr[j];
if (sum % TOTAL_NUM === 0) {
found = true;
// output result
console.log('Sum = %d, n = %d, m = %d', sum, i, j);
break;
}
}
if (found) break;
}
As you can see, this code requires N * (N-1) / 2 loop, and no memory. Even for very large N, it would take a few milliseconds to find n and m.
It took about 20~80ms to find a solution for N = 10000000 on my computer(Core i5 4460 # 2.90GHz).
I'm trying to write a function that takes an array of strings(strarr) and an integer(k) as parameters and returns the longest string made up of k amount of consecutive strings within the array, not separated by commas. I need to call on strarr.length quite often during the function, but I keep getting an error saying that it cannot read that parameter's length.
This is my first time dealing with this issue and I have not found great internet search results for solutions. I suspect that I'm missing something very obvious. I have tried pushing the values of the strarr array parameter into a new array and still no luck.
So if I had const = ['apple','pineapple','banana','strawberry'] passed as my strarr parameter and 2 passed as k, then it should return 'bananastrawberry' because it is the longest consecutive pair of strings within the array.
const arr = ['apple', 'pineapple', 'banana', 'strawberry']
function longestConsec(strarr, k) {
if (strarr.length === 0) {
return "";
} else if (k > strarr.length) {
return "";
} else if (k <= 0) {
return "";
}
let longest = "";
let strLeng = 0;
for (let i = 0; i < strarr.length; i++) {
for (let j = i + (k - 1); j > 0; j--) {
strLeng += strarr[j].length;
}
if (strLeng > longest.length) {
longest = strarr.slice(i, (i + k)).join("");
}
}
return longest;
}
console.log(longestConsec(arr, 2))
As mentioned, you are trying to access an index that doesn't exist in you array.
A quick fix might be:
const arr = ['apple', 'pineapple', 'banana', 'strawberry']
function longestConsec(strarr, k) {
if (strarr.length === 0) {
return "";
} else if (k > strarr.length) {
return "";
} else if (k <= 0) {
return "";
}
let longest = "";
let strLeng = 0;
for (let i = 0; i < strarr.length; i++) {
for (let j = i + (k - 1); j > 0; j--) {
if (j >= strarr.length) {
break;
}
strLeng += strarr[j].length;
}
if (strLeng > longest.length) {
longest = strarr.slice(i, (i + k)).join("");
}
}
return longest;
}
console.log(longestConsec(arr, 2))
But I would suggest to see if there is better solution than adding a break statement.
Mistakes you did
In the inner for loop, for (let j = i + (k - 1); j > 0; j--), you're counting from i + k - 1. But what if i is the last index of array (strarr.length == 10 and i == 9) and k == 2? Then your loop starts at j = 9 + 2 - 1 = 10 and one line below, you try to do strLeng += strarr[10].length, but strarr[10] is not defined.
It also seems unnecessary to create strings before you're done finding the longest one. You could instead just remember start index of your last longest string instead.
How to make it better
Let's look at the requirements. For each i in the array, you want to merge k consecutive strings and keep the longest combination. From that follows:
i + k - 1 must never be larger than strarr.length. Since the i is the only variable here, we need to limit it by only looping up to strarr.length - k + 1.
If k == strarr.length, there is only one string you can make - strarr.join("")
Finally, there's an idea that you probably do not need nested loop at all. For every i, you simply subtract the length of the last string in your current window and add a new one. See image:
So with that in mind, I would propose following version of your code:
function longestConsec(strarr, k) {
// Cannot create any joined string with k greater than length
if(strarr.length < k) {
return "";
}
else if(k <= 0) {
return "";
}
else if(strarr.length == k) {
return strarr.join("");
}
let longestIndex = -1;
let longestLength = 0;
// length of our current group of strings
let currentLength = 0;
const maxLen = strarr.length;
for(let i=0; i<maxLen; ++i) {
// Forget the first strings length
if(i >= k) {
currentLength -= strarr[i-k].length;
}
// add the current strings length
currentLength += strarr[i].length;
// check if this is the largest length and save it's index
// Only possible after processing at least k strings
// Eg when i==1, we already went through 2 strings at this point
if(i >= k-1) {
if(currentLength > longestLength) {
const startIndex = i-k+1;
longestLength = currentLength;
longestIndex = startIndex;
}
}
}
return strarr.slice(longestIndex, (longestIndex + k)).join("");
}
Here's a jsFiddle test: https://jsfiddle.net/32g5oqd1/2/
i solving a challenge of Hacker rank . it about how anagrams. i give two string input and i have to find ...
Print a single integer denoting the number of characters you must delete to make the two strings anagrams of each other.
i have detected if it's anagrams or not and difference. but now can do the rest of it dont have any ideas.please help.
function main() {
var a = readLine();
var b = readLine();
var sum1 = 0 ;
var sum2 = 0 ;
for (var i= 0; i<= a.length-1; i++ )
{
sum1 = sum1 + a.charCodeAt(i);
}
console.log(sum1);
for (var i= 0; i<= b.length-1; i++ )
{
sum2 = sum2 + b.charCodeAt(i);
}
console.log(sum2);
if(sum1== sum2)
{
console.log("anagrams");
}
else
{
console.log("not anagram");
var diff = sum1 - sum2;
console.log(diff);
/// what to do now ?
}
}
I have solved this on hackerRank by using the object approach to count the frequency of letters if you are still looking for a reasonable solution.
function makeAnagrams(a,b){
let charA=buildcharMap(a)
let charB=buildcharMap(b)
let characters=[]
let counter=0
for(let char in charA){
if(charA[char] && charB[char]){
if(charA[char]===charB[char]){ //same frequency
continue;
}
else{
if(charA[char]>charB[char]){
counter=counter+ charA[char]-charB[char]
}
else{
counter=counter+ charB[char]-charA[char]
}
}
}
else{
counter=counter+charA[char]
}
}
for(let char in charB){
if(charB[char] && charA[char]===undefined){
counter=counter+charB[char]
}
}
return counter;
}
function buildcharMap(str){
var charMap={}
for(let char of str){
if (charMap[char]===undefined){
charMap[char]=1
}
else{
charMap[char]+=1
}
}
return charMap
}
console.log(makeAnagrams('cde','abc'))
I have solve this question on hackerearth, i took slightly different approach.
What i have done in this code is that i have check for all the characters and replace the character with "#" sign if both characters in string are same, then i count all the "#" signs in one of the strings that is modified, and then subtracted value of that count multiplied by two(because... they are similar in both strings) from total length of both strings.
Here is my code, hope you can convert it into javascript. ->
import java.util.Scanner;
public class Anagrams {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int Testcases = scanner.nextInt();
String[] str1 = new String[1000];
String[] str2 = new String[1000];
// Taking input
for (int i = 0; i < Testcases; i++) {
str1[i] = scanner.next().toLowerCase();
str2[i] = scanner.next().toLowerCase();
}
// For Total Length of both strings
int TotalLength[] = new int[Testcases];
// For counting "#" signs
int count[] = new int[Testcases];
// Loop through TestCases
for (int i = 0; i < Testcases; i++) {
TotalLength[i] = str1[i].length() + str2[i].length();
for (int j = 0; j < str1[i].length(); j++) {
for (int k = 0; k < str2[i].length(); k++) {
// If both characters are similar, then replace those characters with "#" signs
if (str1[i].charAt(j) == str2[i].charAt(k)) {
str1[i] = str1[i].replaceFirst(Character.toString(str1[i].charAt(j)),"#");
str2[i] = str2[i].replaceFirst(Character.toString(str2[i].charAt(k)),"#");
}
}
}
}
// Counting "#" signs from one string
for (int i = 0; i < Testcases; i++) {
count[i] = 0;
char[] c1 = str1[i].toCharArray();
for (char c: c1) {
if(c == '#'){
count[i]++;
}
}
}
// Output
for (int i = 0; i < Testcases; i++) {
System.out.println(TotalLength[i] - 2*count[i]);
}
scanner.close();
}
}
You are really just looking for the sum of the differences in later frequency. You can just count the frequencies into an 26 item array (the rules tell you there will only be lower case numbers). Then subtract each array from the other item by item but item and add the whole thing up. Seems like it only need about four lines of code:
function makeAnagram(a, b) {
const makeCountArray = (str) => [...str].reduce((a, c) => (a[c.charCodeAt(0) - 97]++, a), Array(26).fill(0))
let a1 = makeCountArray(a)
let a2 = makeCountArray(b)
return a1.reduce((a, c, i) => a + Math.abs(c - a2[i]), 0)
}
// test case expected: 30
let count = makeAnagram('fcrxzwscanmligyxyvym', 'jxwtrhvujlmrpdoqbisbwhmgpmeoke')
console.log(count)
Here's another approach using Map() of all the 26 alphabets in each string
function makeAnagram(a, b) {
let result = 0;
const alphabets = 'abcdefghijklmnopqrstuvwxyz'.split('');
const getCharCountMap = str => {
const strArray = str.split('');
let charMap = new Map();
alphabets.forEach(alphabet => charMap.set(alphabet, 0));
strArray.forEach(letter => charMap.set(letter, charMap.get(letter) + 1));
return charMap;
};
const aMap = getCharCountMap(a);
const bMap = getCharCountMap(b);
alphabets.forEach(alphabet => {
result = result + Math.abs(aMap.get(alphabet) - bMap.get(alphabet));
});
return result;
}
There are a lot of posts on the easiest way to find duplicates in two arrays, but what is absolute fastest way? Is there a way to avoid using two for loops and get the function from O(n^2) time to O(n) time? The arrays I have contain ~1000 items each. Before running the function I check which array is longer and use that array as the toCheckAgainst variable.
var containingBoth = [];
function checkArrays(toCheck, toCheckAgainst){
for(var i=0;i<toCheck.length;i+=1){
for(var j=0;j<toCheckAgainst.length;j+=1){
if (toCheck[i] === toCheckAgainst[j]) {
containingBoth.push(toCheck[i]);
}
}
}
}
This can be the another way to achieve this.Your current solution have the looping on both of the arrays and looping on the longest one which slower down the process in large arrays e.g if one longest array has 1000 vals and shorter array has only 2 in that case you are looping 1000 values to find out the dupes which can not be more than 2 in that case.
Below solution loop is only on the array which is shorter than the other array because we are only interested in dupes and even if both arrays are of same length below solution is faster because in your solution you are looping on both arrays whereas below code just loop on one.
Did some testing on comparing difference in speed in Niles code and mine see the results here Niles Code and my code and its approximately 50% faster with the arrays of 1000 values each
var arr1 = ["Test1", "test2", "test3","test5","test6","test4"];
var arr2 = ["test1", "test4","test5","test6","test2","Test1"];
var result = [];
(arr1.length>arr2.length?arr2:arr1).forEach(function(key) {
if (-1 != (arr1.length>arr2.length?arr1:arr2).indexOf(key) && -1 == result.indexOf(key))
result.push(key);
}, this);
alert(result); //duplicate values arr
Edited to add example code
You can do it in O(n) if both arrays--with lengths "k" and "l" respectively--are already sorted. You can do it by merging the two arrays (not in memory, of course, just algorithmically) like in merge-sort with k+l comparisons.
If both arrays are not sorted at all you can do it in O(n log n) (e.g. with the merge-sort mentioned above) with O(n²) comparisons and because you can do your task with brute force in O(n²) already, sorting the arrays would be redundant here.
But not all sets are completely unsorted, especially if they are big. If we take quicksort as an example you can expect O(n log n) on average with O(n log n) comparisons. But be aware that the worst case of quicksort is O(n²) when the set is already sorted!
A very simple way if your arrays are sorted and contain no duplicates:
Take the individual entries of the smaller array and do a binary search for them in the larger array -> O(n log n) (binary search is O(log n) and you do it n times). The smaller array does not even have to be sorted if it is guaranteed that it contains no duplicates.
Summary: you can do it faster than O(n²). It depends on the input how fast "faster" actually gets but you can get it down to O(n) (plus a small constant) in the best case and O(n log n) on average.
'use strict'
var primesieve;
var buffer;
var primelimit;
function clear(where) {
primesieve[where >>> 5] &= ~((1 << (31 - (where & 31))));
}
function get(where) {
return ((primesieve[where >>> 5] >>> ((31 - (where & 31)))) &
1);
}
function nextset(from) {
while (from < primelimit && !get(from)) {
from++;
}
if (from === primelimit && !get(from)) {
return - 1;
}
return from;
}
function fillsieve(n) {
var k,
r,
j;
n = n + 1;
primelimit = n - 1;
k = Math.ceil(n / 32);
if (typeof ArrayBuffer !== 'function') {
buffer = new ArrayBuffer(k * 4);
} else {
buffer = k;
}
primesieve = new Uint32Array(buffer);
while (k--) {
primesieve[k] = 0xffffffff;
}
clear(0);
clear(1);
for (k = 4; k < n; k += 2) {
clear(k);
}
r = Math.floor(Math.sqrt(n));
k = 0;
while (k < n) {
k = nextset(k + 1);
if (k > r || k < 0) {
break;
}
for (j = k * k; j < n; j += 2 * k) {
clear(j);
}
}
}
function approx_limit(prime_pi) {
if (prime_pi < 10) {
return 30;
}
// see first term of expansion of li(x)-li(2)
return Math.ceil(prime_pi * (Math.log(prime_pi * Math.log(prime_pi))));
}
function primes(prime) {
var ret,
k,
count,
i;
ret = [];
k = 0;
i = 0;
count = prime;
while (count--) {
k = nextset(k + 1);
if (k > primelimit || k < 0) {
break;
}
ret[i++] = k;
}
return ret;
}
// very simple binary search
Array.prototype.bsearch = function(needle) {
var mid, lo = 0;
var hi = this.length - 1;
while (lo <= hi) {
mid = Math.floor((lo + hi) / 2);
if (this[mid] > needle) {
hi = mid - 1;
} else if (this[mid] < needle) {
lo = mid + 1;
} else {
return this[mid];
}
}
// assumes no entry "-1", of course
return -1;
};
var limit = 10 * 1000;
var a, b, b_sorted, u;
var a_length, b_length, u_length;
fillsieve(approx_limit(limit));
// the first array is filled with primes, sorted and unique
a = primes(limit);
// the second array gets filled with an unsorted amount of
// integers between the limits 0 (zero) and "limit".
b = [];
for(var i = 0;i < limit;i++){
b[i] = Math.floor( Math.random() * (limit + 1));
}
a_length = a.length;
b_length = b.length;
console.log("Length of array a: " + a_length);
console.log("Length of array b: " + b_length);
var start, stop;
u = [];
// Brute-force
start = performance.now();
for(var i = 0; i < a_length; i++){
for(var j = 0; j< b_length; j++){
if(a[i] == b[j] && a[i] != u[u.length - 1]){
u.push(a[i]);
}
}
}
stop = performance.now();
console.log("Brute force = " + (stop - start));
console.log("u-length = " + u.length);
console.log(u.join(","));
u = [];
b_sorted = [];
// work on copy
for(var i = 0; i < b_length; i++) b_sorted[i] = b[i];
var entry;
// Sort the unsorted array first, than do a binary search
start = performance.now();
// ECMA-script's arrays sort() function sorts lexically
b_sorted.sort(function(a,b){return a - b;});
for(var i = 0; i < a_length; i++){
entry = b_sorted.bsearch(a[i])
if( entry != -1 && entry != u[u.length - 1]){
u.push(entry);
}
}
stop = performance.now();
console.log("Binary search = " + (stop - start));
console.log("u-length = " + u.length);
console.log(u.join(","));
This runs on my little AMD A8-6600K in around 56 seconds with the brute force algorithm and in about 40 milliseconds (yes, milliseconds!) with the binary search and that number even includes the sorting of the array.
I'm trying to find an easy way to loop (iterate) over an array to find all the missing numbers in a sequence, the array will look a bit like the one below.
var numArray = [0189459, 0189460, 0189461, 0189463, 0189465];
For the array above I would need 0189462 and 0189464 logged out.
UPDATE : this is the exact solution I used from Soufiane's answer.
var numArray = [0189459, 0189460, 0189461, 0189463, 0189465];
var mia= [];
for(var i = 1; i < numArray.length; i++)
{
if(numArray[i] - numArray[i-1] != 1)
{
var x = numArray[i] - numArray[i-1];
var j = 1;
while (j<x)
{
mia.push(numArray[i-1]+j);
j++;
}
}
}
alert(mia) // returns [0189462, 0189464]
UPDATE
Here's a neater version using .reduce
var numArray = [0189459, 0189460, 0189461, 0189463, 0189466];
var mia = numArray.reduce(function(acc, cur, ind, arr) {
var diff = cur - arr[ind-1];
if (diff > 1) {
var i = 1;
while (i < diff) {
acc.push(arr[ind-1]+i);
i++;
}
}
return acc;
}, []);
console.log(mia);
If you know that the numbers are sorted and increasing:
for(var i = 1; i < numArray.length; i++) {
if(numArray[i] - numArray[i-1] != 1) {
//Not consecutive sequence, here you can break or do whatever you want
}
}
ES6-Style
var arr = [0189459, 0189460, 0189461, 0189463, 0189465];
var [min,max] = [Math.min(...arr), Math.max(...arr)];
var out = Array.from(Array(max-min),(v,i)=>i+min).filter(i=>!arr.includes(i));
Result: [189462, 189464]
Watch your leading zeroes, they will be dropped when the array is interpreted-
var A= [0189459, 0189460, 0189461, 0189463, 0189465]
(A returns [189459,189460,189461,189463,189465])
function absent(arr){
var mia= [], min= Math.min.apply('',arr), max= Math.max.apply('',arr);
while(min<max){
if(arr.indexOf(++min)== -1) mia.push(min);
}
return mia;
}
var A= [0189459, 0189460, 0189461, 0189463, 0189465];
alert(absent(A))
/* returned value: (Array)
189462,189464
*/
To find a missing number in a sequence, First of all, We need to sort an array. Then we can identify what number is missing. I am providing here full code with some test scenarios. this code will identify only missing positive number, if you pass negative values even then it gives positive number.
function findMissingNumber(inputAr) {
// Sort array
sortArray(inputAr);
// finding missing number here
var result = 0;
if (inputAr[0] > 1 || inputAr[inputAr.length - 1] < 1) {
result = 1;
} else {
for (var i = 0; i < inputAr.length; i++) {
if ((inputAr[i + 1] - inputAr[i]) > 1) {
result = inputAr[i] + 1;
}
}
}
if (!result) {
result = inputAr[inputAr.length - 1] + 1;
}
return result;
}
function sortArray(inputAr) {
var temp;
for (var i = 0; i < inputAr.length; i++) {
for (var j = i + 1; j < inputAr.length; j++) {
if (inputAr[j] < inputAr[i]) {
temp = inputAr[j];
inputAr[j] = inputAr[i];
inputAr[i] = temp;
}
}
}
}
console.log(findMissingNumber([1, 3, 6, 4, 1, 2]));
console.log(findMissingNumber([1, 2, 3]));
console.log(findMissingNumber([85]));
console.log(findMissingNumber([86, 85]));
console.log(findMissingNumber([0, 1000]));
This can now be done easily as a one-liner with the find method:
const arr = [1,2,3,5,6,7,8,9];
return arr.find((x,i) => arr[i+1]-x > 1) + 1
//4
const findMissing = (arr) => {
const min = Math.min(...arr);
const max = Math.max(...arr);
// add missing numbers in the array
let newArr = Array.from(Array(max-min), (v, i) => {
return i + min
});
// compare the full array with the old missing array
let filter = newArr.filter(i => {
return !arr.includes(i)
})
return filter;
};
const findMissing = (numarr) => {
for(let i = 1; i <= numarr.length; i++) {
if(i - numarr[i-1] !== 0) {
console.log('found it', i)
break;
} else if(i === numarr.length) console.log('found it', numarr.length + 1)
}
};
console.log(findMissing([1,2,3,4,5,6,7,8,9,10,11,12,13,14]))
It would be fairly straightforward to sort the array:
numArray.sort();
Then, depending upon what was easiest for you:
You could just traverse the array, catching sequential patterns and checking them as you go.
You could split the array into multiple arrays of sequential numbers and then check each of those separate arrays.
You could reduce the sorted array to an array of pairs where each pair is a start and end sequence and then compare those sequence start/ends to your other data.
function missingNum(nums){
const numberArray = nums.sort((num1, num2)=>{
return num1 - num2;
});
for (let i=0; i < numberArray.length; i++){
if(i !== numberArray[i]){
return i;
}
}
}
console.log(missingNum([0,3,5,8,4,6,1,9,7]))
Please check below code.....
function solution(A) {
var max = Math.max.apply(Math, A);
if(A.indexOf(1)<0) return 1;
var t = (max*(max+1)/2) - A.reduce(function(a,b){return a+b});
return t>0?t:max+1;
}
Try as shown below
// Find the missing number
let numArray = [0189459, 0189460, 0189461, 0189463, 0189468];
let numLen = numArray.length;
let actLen = Number(numArray[numLen-1])-Number(numArray[0]);
let allNumber = [];
for(let i=0; i<=actLen; i++){
allNumber.push(Number(numArray[0])+i);
}
[...allNumber].forEach(ele=>{
if(!numArray.includes(ele)){
console.log('Missing Number -> '+ele);
}
})
I use a recursive function for this.
function findMissing(arr, start, stop) {
var current = start,
next = stop,
collector = new Array();
function parseMissing(a, key) {
if(key+1 == a.length) return;
current = a[key];
next = a[key + 1];
if(next - current !== 1) {
collector.push(current + 1);
// insert current+1 at key+1
a = a.slice( 0, key+1 ).concat( current+1 ).concat( a.slice( key +1 ) );
return parseMissing(a, key+1);
}
return parseMissing(a, key+1);
}
parseMissing(arr, 0);
return collector;
}
Not the best idea if you are looking through a huge set of numbers. FAIR WARNING: recursive functions are resource intensive (pointers and stuff) and this might give you unexpected results if you are working with huge numbers. You can see the jsfiddle. This also assumes you have the array sorted.
Basically, you pass the "findMissing()" function the array you want to use, the starting number and stopping number and let it go from there.
So:
var missingArr = findMissing(sequenceArr, 1, 10);
let missing = [];
let numArray = [3,5,1,8,9,36];
const sortedNumArray = numArray.sort((a, b) => a - b);
sortedNumArray.reduce((acc, current) => {
let next = acc + 1;
if (next !== current) {
for(next; next < current; next++) {
missing.push(next);
}
}
return current;
});
Assuming that there are no duplicates
let numberArray = [];
for (let i = 1; i <= 100; i++) {
numberArray.push(i);
}
let deletedArray = numberArray.splice(30, 1);
let sortedArray = numberArray.sort((a, b) => a - b);
let array = sortedArray;
function findMissingNumber(arr, sizeOfArray) {
total = (sizeOfArray * (sizeOfArray + 1)) / 2;
console.log(total);
for (i = 0; i < arr.length; i++) {
total -= arr[i];
}
return total;
}
console.log(findMissingNumber(array, 100));
Here is the most efficient and simple way to find the missing numbers in the array. There is only one loop and complexity is O(n).
/**
*
* #param {*} item Takes only the sorted array
*/
function getAllMissingNumbers(item) {
let first = 0;
let second = 1;
let currentValue = item[0];
const container = [];
while (first < second && item[second]) {
if ((item[first] + 1) !== item[second]) { // Not in sequence so adds the missing numbers in an array
if ((currentValue + 1) === item[second]) { // Moves the first & second pointer
first = second;
second++;
currentValue = item[first];
} else { // Adds the missing number between two number
container.push(++currentValue);
}
} else { // Numbers are in sequence so just moves the first & second pointer
first = second;
second++;
currentValue = item[first];
}
}
return container;
}
console.log(getAllMissingNumbers([0189459, 0189460, 0189461, 0189463, 0189465].sort( (a, b) => a - b )));
console.log(getAllMissingNumbers([-5,2,3,9]));
Adding one more similar method
Find the min and max of the numbers in the array
Loop with the max and min numbers to get the full list
compare the full list of numbers with the input array to get the difference
const array = [0189459, 0189460, 0189461, 0189463, 0189465]
const max = Math.max(...array)
const min = Math.min(...array)
let wholeNumber = []
for(var i = min ;i<=max ;i++ ){
wholeNumber.push(i)
}
const missing = wholeNumber.filter((v)=>!array.includes(v))
console.log('wholeNumber',wholeNumber)
console.log('missingNumber',missing)
Here's a variant of #Mark Walters's function which adds the ability to specify a lower boundary for your sequence, for example if you know that your sequence should always begin at 0189455, or some other number like 1.
It should also be possible to adjust this code to check for an upper boundary, but at the moment it can only look for lower boundaries.
//Our first example array.
var numArray = [0189459, 0189460, 0189461, 0189463, 0189465];
//For this array the lowerBoundary will be 0189455
var numArrayLowerBoundary = 0189455;
//Our second example array.
var simpleArray = [3, 5, 6, 7, 8, 10, 11, 13];
//For this Array the lower boundary will be 1
var simpleArrayLowerBoundary = 1;
//Build a html string so we can show our results nicely in a div
var html = "numArray = [0189459, 0189460, 0189461, 0189463, 0189465]<br>"
html += "Its lowerBoundary is \"0189455\"<br>"
html += "The following numbers are missing from the numArray:<br>"
html += findMissingNumbers(numArray, numArrayLowerBoundary);
html += "<br><br>"
html += "simpleArray = [3, 5, 6, 7, 8, 10, 11, 13]<br>"
html += "Its lowerBoundary is \"1\".<br>"
html += "The following numbers are missing from the simpleArray:<br>"
html += findMissingNumbers(simpleArray, simpleArrayLowerBoundary);
//Display the results in a div
document.getElementById("log").innerHTML=html;
//This is the function used to find missing numbers!
//Copy/paste this if you just want the function and don't need the demo code.
function findMissingNumbers(arrSequence, lowerBoundary) {
var mia = [];
for (var i = 0; i < arrSequence.length; i++) {
if (i === 0) {
//If the first thing in the array isn't exactly
//equal to the lowerBoundary...
if (arrSequence[i] !== lowerBoundary) {
//Count up from lowerBoundary, incrementing 1
//each time, until we reach the
//value one less than the first thing in the array.
var x = arrSequence[i];
var j = lowerBoundary;
while (j < x) {
mia.push(j); //Add each "missing" number to the array
j++;
}
} //end if
} else {
//If the difference between two array indexes is not
//exactly 1 there are one or more numbers missing from this sequence.
if (arrSequence[i] - arrSequence[i - 1] !== 1) {
//List the missing numbers by adding 1 to the value
//of the previous array index x times.
//x is the size of the "gap" i.e. the number of missing numbers
//in this sequence.
var x = arrSequence[i] - arrSequence[i - 1];
var j = 1;
while (j < x) {
mia.push(arrSequence[i - 1] + j); //Add each "missing" num to the array
j++;
}
} //end if
} //end else
} //end for
//Returns any missing numbers, assuming that lowerBoundary is the
//intended first number in the sequence.
return mia;
}
<div id="log"></div> <!-- Just used to display the demo code -->