how to find longest common subarray - javascript

here is my problem: I have 5 arrays of integer like these in javascript:
array1 = [0, 1, 2, 3, 4];
array2 = [9, 1, 2, 3, 4];
array3 = [10, 1, 2, 11, 4];
array4 = [12, 1, 2, 13, 4];
array5 = [14, 1, 2, 15, 4];
I have to find the longest common subarray. In this case I have to retrieve the following subarray: [1, 2, 4].
For the records, I won't find repetitions inside arrays and my main goal is not execution speed.
thanks

here is the solution using Set in Javascript
var myArray = [array1 , array2 ,array3 , array4 ,array5];
let keys = new Set();
myArray.forEach(arr => arr.forEach(el => keys.add(el) ))
var common = [...keys].filter(key => myArray.every(arr => arr.includes(key)))
console.log(common);

#define MAX(a,b) a>b?a:b
int main(int argc, char* argv[])
{
if(argc < 2)
return -1;
int x = strlen(argv[1])+1;
int y = strlen(argv[2])+1;
int i,j,k,l;
int longest =0;
char* LCS = (char*)malloc(sizeof(char)*MAX(x,y));
int** arr = (int**)malloc(sizeof(int*)*x);
for(i=0;i<=y;i++)
arr[i] =(int*) malloc(sizeof(int)*y);
for(i=0;i<=x;i++)
for(j=0;j<=y;j++)
{
arr[i][j] = 0;
}
for(i=0;i<x;i++)
for(j=0;j<y;j++)
{
if(argv[1][i] == argv[2][j])
arr[i+1][j+1] = arr[i][j]+1;
if(arr[i+1][j+1] > longest)
{
longest =arr[i+1][j+1];
memset(LCS,0,MAX(x,y));
for( k=0,l=i;k<=longest;k++,l--)
LCS[k] = argv[1][l];
}
}
printf(" %s",argv[2]);
for(i=0;i<x;i++)
{
printf("\n%c",argv[1][i]);
for(j=0;j<y;j++)
{
printf("%d",arr[i][j]);
}
}
printf("\nLongest Common Subarray : %s\n",LCS);
return 0;
}

Try this:
var array1 = [0, 1, 2, 3, 4];
var array2 = [9, 1, 2, 3, 4];
var array3 = [10, 1, 2, 11, 4];
var array4 = [12, 1, 2, 13, 4];
var array5 = [14, 1, 2, 15, 4];
// join everything into one array
var all = array1.join(',')+','+array2.join(',')+','+array3.join(',')+','+array4.join(',')+','+array5.join(',');
all = all.split(',');
// get an object with all unique numbers as keys
var keys = {};
for(var i=0; i<all.length; i++) keys[all[i]] = 1;
console.log(keys);
// generate an array with values present in all arrays
var common = [];
for(var x in keys) {
if(array1.indexOf(parseInt(x)) != -1 && array2.indexOf(parseInt(x)) != -1 && array3.indexOf(parseInt(x)) != -1 && array4.indexOf(parseInt(x)) != -1 && array5.indexOf(parseInt(x)) != -1) {
common.push(x);
}
}
console.log(common);

I guess this can give you a good start:
My script will return you an object with the count of each elements. But for now, it takes the first array as base.
var array1 = [0, 1, 2, 3, 4];
var array2 = [9, 1, 2, 3, 4];
var array3 = [10, 1, 2, 11, 4];
var array4 = [12, 1, 2, 13, 4];
var array5 = [14, 1, 2, 15, 4];
var array6 = [13, 1, 2, 18, 4];
var mainArr = [array1, array2, array3, array4, array5, array6]
function getCommonElement(arr){
var subLength = arr[0].length;
var resultArr = new Array();
var ret = new Object();
for(var k=0;k<subLength;k++){
var temp = new Array();
for(var i=0;i<arr.length;i++){
temp.push(arr[i][k]);
}
resultArr.push(temp);
}
for(var i=0;i<arr[0].length;i++){
ret[arr[0][i]+''] = resultArr[i].join('').split(arr[0][i]+'').length - 1;
}
return ret;
}
Cheers.

/**
longest common subarray b/w 2 arrays
a = [2,3,4,5,6,7,8], b = [6,7,8,4,5,2,3]
ans = 6,7,8
basically create a 2d arr and if elements match dp[i][j] = 1 + dp[i-1][j-1];
if dp[i][j] > maxLen, update maxLen and store the index
Now that we have the maxLen, subarray will be from (index - maxLen) till index.
*/
int[] finMaxCommon(int[] a, int[] b){
int m = a.length, n = b.length, maxLen = 0;
int[][] dp = new int[m+1][n+1];
// i want a 0th row why? m->out of bounds; comparing i-1; i->1 then i-1 will be 0
for (int i = 1; i<=m; i++){
for(int j = 1; j<=n; j++){
if(a[i-1] == b[j-1]) {
dp[i][j] = 1 + dp[i-1][j-1];
maxLen = Math.max(maxLen, dp[i][j]);
}
}
}
// endIndex = 6, 3, a[6-3+1], a[6]
return new int[]{a[endIndex-maxLen+1], [endIndex]};
}
dry run
0,6,7,8,4,5,2,3
0, 0 //
2, 1 // (2,2) i = 1, j = 6 1 + dp[0][5]
3, 2 // (3,3) i = 2, j = 7 1 + dp[1][6]
4,
5,
6, 1
7, 2
8, 3

Related

How to add an array of elements in order?

I have an array: const arr = [1, 2, 5, 10];
How I can transform it to const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]?;
A simple way to do it without hard-coding the number of iterations is to get the minimum value from the array and the maximum and then fill the numbers in-between them.
Here's one way to do it
const arr = [1, 2, 5, 10];
var highest = Math.max(...arr);
var minimum = Math.min(...arr);
var output = [];
for(var i = minimum; i <= highest; i++){
output.push(i);
}
console.log(output);
Here's a one liner solution based on Adriani6 answer:
const arr = [1, 2, 5, 10];
var highest = Math.max(...arr);
var minimum = Math.min(...arr);
const newArr = ([...Array(highest+1).keys()]).slice(minimum);
console.log(newArr);
const arr = [1, 2, 5, 10];
for(let i = 1; i <= 10; i++) { // Loop from 1 till 10, including 10
if (!arr.includes(i)) { // If arr does not include 'i'
arr.splice(i - 1, 0, i); // We insert it into the array
// -1, because arrays start at 0
}
}
You could take a nested while statement and splice missing items.
var array = [1, 2, 5, 10],
i = array.length;
while (i--) while (array[i - 1] + 1 < array[i]) array.splice(i, 0, array[i] - 1);
console.log(...array);

Find Matches in Array

I have array1 = [4, 5, 6, 7, 4, 5]; and array2 = [4, 5].
And I want to match array2 in array1 and to output the number of times it matched.
var array1 = [4, 5, 6, 7, 4, 5];
var array2 = [4, 5];
function match(a1, a2) {
//matches 4,5 twice bc it is in array1
}
match(array1, array2) //output: 2;
You have to use a nested loop and compare each index of both arrays with each other.
var count = 0;
for (var i = 0; i < a1.length; i++)
{
for (var j = 0; j < a2.length; j++)
{
if (a1[i]==a2[j])
{
count +=1;
}
}
}
The best way to solve your problem is by intersection.
The solution for your problem: https://stackoverflow.com/a/1885660/4120554
What you're asking for is called an intersection. If you're only interested in the number of matches, this function should do the trick:
var array1 = [4, 5, 6, 7, 4, 5];
var array2 = [4, 5];
function intersectCount(arr1, arr2) {
var c = 0;
for(const item of arr2) {
if (arr1.indexOf(item) != -1) c++;
}
return c;
}
intersectCount(array1, array2); // result: 2
You can use below code for your question;
var array1 = [4, 5, 6, 7, 4, 5];
var array2 = [4, 5];
function match(a1, a2) {
var result = [];
for(const item of a2) {
if (a1.indexOf(item) > -1 ) {
result.push (item);
}
}
return result.length;
}
If you want to compare each index:
var match = (arr1,arr2)=>arr1.filter((el,i)=>el === arr2[i]).length;
If you want to count all elements that exist in both arrays, may unify one through a set:
function match(arr1,arr2){
var set = new Set( arr2 );
return arr1.filter( el => set.has(el) ).length;
}

Make average of values inside array to smooth graph line

I have an array which represents the points of a graph with different values like the following one:
var array = [5, 3, 4, 1, 2];
I would like to loop through it and create a new array where the new values are:
An average between the value preceding it and the one coming after it.
Placed among the existing ones.
This means that array[0] will remain at the same position, while the other values will be pushed of one position. The new array should look like this:
var newArray = [5, 4, 3, 3.5, 4, 2.5, 1, 1.5, 2];
Do you have an idea on how to achieve this? Thanks in advance to your replies!
var array = [5, 3, 4, 1, 2];
var newArr = [array[0]]; // start the array with the first from the original
array.reduce((a, b) => {
newArr.push((a + b) / 2, b);
return b;
});
console.log(newArr);
var array = [5, 3, 4, 1, 2];
var newArray = [];
newArray.push(array[0]);
for(var i=0; i < array.length-1; i++)
{
var first = array[i];
var second = array[i+1];
var avg = (first+second)/2;
newArray.push(avg);
newArray.push(second);
}
https://jsfiddle.net/5utkvge8/
You are going to want to loop through your original array, pushing each number to the new one, and if you are not on the final element, get the average of array[i] and array[i+1]
var array = [5, 3, 4, 1, 2];
var newArray = [];
for (var i = 0; i < array.length; i++)
{
newArray.push(array[i])
if (!isNaN(array[i+1]))
{
newArray.push((array[i] + array[i+1]) / 2)
}
}
or in a functional, no-side effects, way:
var array = [5, 3, 4, 1, 2];
var newArray = array.reduce((result, value, index, array) => result.concat(index > 0 && index < array.length ? [(array[index-1] + value)/2, value] : value), [])
In case you can modify the original array:
var array = [5, 3, 4, 1, 2],
len = array.length * 2 - 2;
for (var i = 1; i < len; i = i + 2) {
array.splice(i, null, (array[i-1] + array[i]) / 2);
}
console.log(array);
let createdArr = []
[5, 3, 4, 1, 2].forEach( (item,index,arr) => {
createdArr.push(item)
if( index !== 0 && index + 1 !== arr.length ){
createdArr.push( (item + arr[ index + 1]) / 2 )
}
} )

Array truncation with splice method

I need to delete occurrences of an element if it occurs more than n times.
For example, there is this array:
[20,37,20,21]
And the output should be:
[20,37,21]
I thought one way of solving this could be with the splice method
First I sort the array it order to make it like this:
[20,20,37,21]
Then I check if the current element is not equal to the next and split the array into chunks, so it should look like:
[20, 20],[37],[21]
Later I can edit the chunk longer than 1 and join it all again.
This is what the code looks like in my head but didn't work in real life
var array = [20, 37, 20, 21];
var chunk = [];
for(i = 0; i < array.length; i++) {
if(array[i] !== array[i + 1]) {
var index = array.indexOf(array[i]);
chunk.push = array.splice(0, index) // cut from zero to last duplicate element
} else
var index2 = a.indexOf(a[i]);
chunk.push(a.splice(0, index));
}
with this code the output is
[[], [20, 20]]
I think It's something in the 'else' but can't figure it out what to fix.
As the logic you want to achieve is to delete n occurrences of element in an array, your code could be as follow:
var array = [1, 1, 3, 3, 7, 2, 2, 2, 2];
var n = 2;
var removeMultipleOccurences = function(array, n) {
var filteredArray = [];
var counts = {};
for(var i = 0; i < array.length; i++) {
var x = array[i];
counts[x] = counts[x] ? counts[x] + 1 : 1;
if (counts[x] <= n) filteredArray.push(array[i])
}
return filteredArray;
}
console.log(removeMultipleOccurences(array, n));
I came up with this one, based on array filter checking repeated values up to a limit, but I can see #Basim's function does the same.
function removeDuplicatesAbove(arr, max) {
if (max > arr.length) {max = arr.length;}
if (!max) {return arr;}
return arr.filter(function (v, i) {
var under = true, base = -1;
for (var n = 0; n < max; n++) {
base = arr.indexOf(v, base+1); if (base == -1) {break;}
}
if (base != -1 && base < i) {under = false;}
return under;
});
}
var exampleArray = [20, 37, 20, 20, 20, 37, 22, 37, 20, 21, 37];
console.log(removeDuplicatesAbove(exampleArray, 3)); // [20, 37, 20, 20, 37, 22, 37, 21]
Always when you use splice() you truncate the array. Truncate the array with the length of same values from the start with the help of lastIndexOf(). It always starts from 0.
[ 1, 1, 1, 2, 2, 2, 3, 4, 4, 5 ] // splice(0, 3)
[ 2, 2, 2, 3, 4, 4, 5 ] // splice(0, 3)
[ 3, 4, 4, 5 ] // splice(0, 1)
[ 4, 4, 5 ] // splice(0, 2)
[ 5 ] // splice(0, 1)
Do this as long as the array length is greater than 0.
var arr = [1, 1, 1, 2, 2, 2, 3, 4, 4, 5];
var res = [];
while (arr.length > 0) {
var n = arr[0];
var last = arr.lastIndexOf(n) + 1;
res.push(n);
arr.splice(0, last);
}
console.log(res);
You can use Array.prototype.reduce(), Array.prototype.filter() to check if n previous elements are the same as current element
let cull = (arr, n) => arr.reduce((res, curr) => [...res
, res.filter(v => v === curr).length === n
? !1 : curr].filter(Boolean), []);
let arrays = [[20,37,20,21], [1,1,3,3,7,2,2,2,2]];
let cullone = cull(arrays[0], 1);
let cullthree = cull(arrays[1], 3);
console.log(cullone // [20, 37, 21]
, cullthree // [1, 1, 3, 3, 7, 2, 2, 2]
);

Looping through two (different lengthed) arrays to produce an alternating output

What is an efficient way of looping through two arrays to produce an alternating output? In JavaScript.
If I have two arrays like this:
var oddNumbers = [1, 3, 5, 7, 9]
var evenNumbers = [2, 4, 6, 8, 10, 12, 14]
NB: The arrays may not be the same length
How can I get the following output?
Output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14
I would have thought this would work:
if (oddNumber.length > evenNumbers.length) {
var large = oddNumbers;
} else {
var large = evenNumbers;
}
for(var i = 0; i < large.length; i++){
if (evenNumbers.length >= i && oddNumbers.length >= i) {
console.log(oddNumbers[i] + ", " + evenNumbers[0]);
} elseif (evenNumbers.length >= i) {
console.log(evenNumbers[0]);
} else {
console.log(oddNumbers[0]);
}
}
But it's pretty messy, any better way of approaching this?
NOTE: These may not necessarily be in a numerical order, or in fact numbers
I would rather do it as follows if you just want to output them:
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
for (var i=0, j=0; i < oddNumbers.length || j < evenNumbers.length;) {
if (i < oddNumbers.length) {
console.log(oddNumbers[i++]);
}
if (j < evenNumbers.length) {
console.log(evenNumbers[j++]);
}
}
If you want to get the merge result as another array you can replace console.log with result.push to push result values on an array named result as follows:
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
var result = [];
for (var i=0, j=0; i < oddNumbers.length || j < evenNumbers.length;) {
if (i < oddNumbers.length) {
result.push(oddNumbers[i++]);
}
if (j < evenNumbers.length) {
result.push(evenNumbers[j++]);
}
}
console.log(result);
This way you iterate both arrays as long as one of them has an element that we haven't visited yet and also prevents iterating over the same index of same array twice. Please note that I used increment in if blocks to save 2 lines of code. You can also move them to the for loop since they won't break if statements.
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
var oLength = oddNumbers.length;
var eLength = evenNumbers.length;
var n = oLength > eLength ? oLength : eLength;
var rez=[];
for(i=0;i<n;i++){
if (i< oLength) rez.push(oddNumbers[i])
if (i<eLength) rez.push(evenNumbers[i])
}
console.log(rez);
var odd = ["A", "C","E","G"];
var even = ["B","D","F"];
var rez=[];
for(i=0;i<(odd.length > even.length ? odd.length : even.length);i++){
if (i< odd.length) rez.push(odd[i])
if (i<even.length) rez.push(even[i])
}
console.log(rez);
The following function accepts two arrays and returns their interleaved values as a new array:
function interleaveArrays(a, b) {
var array = [],
limit = a.length >= b.length ? a.length : b.length;
index = 0;
while (index < limit) {
a[index] && array.push(a[index]);
b[index] && array.push(b[index]);
index += 1;
}
return array;
}
Calling the function like so:
var oddNumbers = [1, 3, 5, 7, 9],
evenNumbers = [2, 4, 6, 8, 10, 12, 14];
console.log(interleaveArrays(oddNumbers, evenNumbers));
Yields:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14 ]
You can then output this in your preferred manner; e.g:
var interleaved = interleaveArrays(oddNumbers, evenNumbers);
// as a loop
interleaved.forEach(function (n) {
console.log(n);
})
// or as a string
console.log(interleaved.join(', '));
// etc.
Hope this helps :)
I'd do something like this.
large = (oddNumber.length >= evenNumbers.length) ? oddNumbers : evenNumbers;
small = (oddNumber.length < evenNumbers.length) ? oddNumbers : evenNumbers;
for(var i = 0; i < large.length; i++){
if(small.length <= i + 1){
console.log(small[i] + ", "+ large[i]);
}
else {
console.log(large[i]);
}
}
A long-hand example of how it can be done. The code can be shrunk for a final solution. The basic principle I'm using is to even out the lengths to take care of the alternating then tag on the tail
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
var oLength = oddNumbers.length;
var eLength = evenNumbers.length;
var oTemp, eTemp, remainder;
if(oLength > eLength) {
eTemp = evenNumbers;
oTemp = oddNumbers.slice(0, eLength);
remainder = oddNumbers.slice(eLength);
} else if (eLength > oLength) {
eTemp = evenNumbers.slice(0, oLength);
oTemp = oddNumbers;
remainder = evenNumbers.slice(oLength);
} else {
eTemp = evenNumbers;
oTemp = oddNumbers;
remainder = [];
}
var final = [];
for(var i=0; i < eTemp.length; i++) {
final.push(oTemp[i]);
final.push(eTemp[i]);
}
final = final.concat(remainder);
alert(final);
I would simply merge the two array and sort it
var oddNumbers = [1, 3, 5, 7, 9];
var evenNumbers = [2, 4, 6, 8, 10, 12, 14];
var mergedArr=oddNumbers.concat(evenNumbers );
console.log(mergedArr.sort(function(a,b){return a-b;}));
See No loop.. No hassle. Very Simple
There will be an extra , on the screen. Add an if statement if you don't want that
for(var i = 0; i < large.length; i++){
if(i<evenNumbers.length)
console.log(evenNumbers[i]+",");
if(i<oddNumber.length)
console.log(evenNumbers[i]+",");
}
try this it will work always either number Array or String Array:
var oddNumber = [1, 3, 5, 7, 9]
var evenNumber = [2, 4, 6, 8, 10, 12, 14]
var margedNumbers = oddNumber.concat(evenNumber);
console.log("before: "+margedNumbers);
margedNumbers.sort(function(a, b){return a-b})
console.log("after: "+margedNumbers)
My solution
var oddNumbers = [1, 3, 5, 7, 9]
var evenNumbers = [2, 4, 6, 8, 10, 12, 14]
var extraElements = (oddNumbers.length > evenNumbers.length) ? oddNumbers.slice(evenNumbers.length) : evenNumbers.slice(oddNumbers.length);
var finalArr = [];
var small = (oddNumbers.length < evenNumbers.length) ? oddNumbers : evenNumbers;
small.forEach((each, index) => {
// merge elements in desired order
finalArr.push(oddNumbers[index]);
finalArr.push(evenNumbers[index]);
})
finalArr = finalArr.concat(extraElements);
alert(finalArr);
Extract the extra elements which makes both array of same length. Then, in a simple iteration, push elements from both array with same index.

Categories