JavaScript Program for Range LCM Queries


LCM stands for the lowest common multiple and the LCM of a set of numbers is the lowest number among all the numbers which are divisible by all the numbers present in the given set. We will see the complete code with an explanation for the given problem. In this article, we will implement the JavaScript program for a range of LCM queries.

Introduction to Problem

In this problem, we are given an array that will contain integers and another array queries that will contain pairwise numbers representing the range from the given array we have to calculate the LCM of all the elements of that given range. For example −

If the given array is: [1, 2, 3, 4, 5, 6] and the queries array is: [ [1,3], [2,5]] then for the first query elements are [2, 3, 4] and 12 is the LCM.

For the second query elements are [3, 4, 5, 6] LCM is 60.

Mathematical Relation Between LCM and GCD

To find the GCD we have a Euclidian formula by the help of which we can find the GCD of two numbers in logarithmic complexity and there is a relation between the LCM and GCD that −

LCM and GCD of a given set A {a1, a2, a3 …. , an} is:
LCM(A) * GCD(A) = (a1 * a2 * a3* … * an)
OR
LCM(A) = (a1 * a2 * a3 … * an) / GCD(A)

So, we will find the GCD and product of all the numbers, and then from there, we can find the LCM of the number in the O(1) operation.

Naive Approach

The naive approach is to traverse over the queries array and for each query find the product of the elements in the given range and GCD. From both values find the LCM and return it. Let us implement it in the code −

Example

// function to find the gcd of the given number 
function gcd(a,b){
   if (a == 0) {
      return b;
   }
   else {
      return gcd(b%a,a);
   }
}

// function to find the lcm 
function lcmRange(arr, l, r){

   // taking gcd as zero because gcd of 0 with any number is that same number 
   var cur_gcd = 0
   var product = 1
   var cur_lcm = arr[l]
   for(var i = l+1 ;i <= r; i++) {
      product = cur_lcm * arr[i];
      cur_gcd = gcd(cur_lcm, arr[i])
      cur_lcm = product/cur_gcd
   }
   console.log("The LCM of the element in the given range from " + l + " to " + r + " is: " + cur_lcm);
}

// defining the array 
var arr = [ 1, 2, 3, 4, 5, 6]

// defining the queries array 
var queries = [[1,3], [2,5]]

// traversing over the array 
for(var i = 0; i< queries.length; i++){
   lcmRange(arr,queries[i][0], queries[i][1])
}

Time and Space Complexity

The time complexity of the above code is O(Q*N*log(D)), where Q is the number of queries, N is the number of elements in the array, and D is the highest number present in the array.

The space complexity of the above code is O(1), as we are not using any extra space.

In the above program, if the number of queries is equal to N then its time complexity is more than N2 which makes this approach inefficient to use. Let us see it’s another approach &miinus;

Segment Tree Approach

Segment Tree is an advanced data structure which is used to divide the problem in segments and then joining them all in the terms of power of 2. This takes some space put for range queries, produces the result in logarithmic time. Let us see its code −

Example

// defining maximum size
var MAX = 1000

// makking tree 
var tree = new Array(4*MAX);

// declaring new array 
var arr = new Array(MAX);

// function for lcm
function lcm(a, b){
   return a*b/gcd(a,b);
}

// function for gcd
function gcd(a, b){
   if (a == 0)	{
      return b
   }
   else{
      return gcd(b%a,a);
   }
}

// Function to creata a segment tree 
function build(first, last, cur_node){

   // base condition 
   if (first == last){
      tree[cur_node] = arr[first];
      return;
   }
   var mid = (first + last)/2
   mid = Math.floor(mid);
   
   // creating left and right segments
   build(first, mid, 2*cur_node);
   build(mid+1, last, 2*cur_node + 1);
   
   // build the parent for current 
   var lcm_l = tree[2*cur_node];
   var lcm_r = tree[2*cur_node+1];
   tree[cur_node] = lcm(lcm_l, lcm_r);
}

// Function to make queries for array range 
function query(first, last, l, r, cur_node){

   // section out of current range
   
   // 1 is safe to return 
   if (last < l || first > r){
      return 1;
   }
   
   // complete inside the current segment
   if (l <= first  && r >= last)
   return tree[cur_node];
   
   // partially inside the current segment 
   var mid = (first+last)/2;
   mid = Math.floor(mid)
   var lcm_l = query(first, mid, l, r, 2*cur_node);
   var lcm_r = query(mid+1, last, l, r, 2*cur_node+1);
   return lcm(lcm_l, lcm_r);
}

// defining the array 
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
arr[5] = 6;

// build the segment tree
build(0, 5, 1);

// defining query array 
var queries = [[1,3], [2,5]]

// traversing over the array 
for(var i = 0; i< queries.length; i++){
   console.log("The LCM of the element in the given range from " + queries[i][0] + " to " + queries[i][1] + " is: " + query(0,5,queries[i][0],queries[i][1],1) );
}

Conclusion

In this tutorial, we have implemented a JavaScript article to find the range lcm queries. We have seen two approaches, one is the naive approach with O(Q*N*log(D)) time complexity and another one is by implementing the segment tree with time complexity of O(Q*log(N)).

Updated on: 14-Apr-2023

83 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements