JavaScript Program for Range LCM Queries

LCM stands for the Least Common Multiple, and the LCM of a set of numbers is the smallest positive integer that is divisible by all the numbers in the given set. In this article, we will implement a JavaScript program to handle range LCM queries efficiently.

Problem Statement

We are given an array of integers and another array of queries. Each query contains a pair of indices representing a range in the original array. For each query, we need to calculate the LCM of all elements within that range.

For example, if the array is [1, 2, 3, 4, 5, 6] and queries are [[1,3], [2,5]]:

  • First query: elements [2, 3, 4] ? LCM = 12
  • Second query: elements [3, 4, 5, 6] ? LCM = 60

Mathematical Relationship Between LCM and GCD

To solve this efficiently, we use the mathematical relationship between LCM and GCD (Greatest Common Divisor):

For two numbers a and b:
LCM(a, b) = (a × b) / GCD(a, b)

For multiple numbers:
LCM can be computed iteratively using this formula

We can find GCD using the Euclidean algorithm with logarithmic time complexity.

Naive Approach

The straightforward approach is to process each query by iterating through the range and computing LCM step by step:

// Function to find GCD using Euclidean algorithm
function gcd(a, b) {
    if (a == 0) {
        return b;
    }
    return gcd(b % a, a);
}

// Function to find LCM of two numbers
function lcm(a, b) {
    return (a * b) / gcd(a, b);
}

// Function to find LCM in a given range
function lcmRange(arr, l, r) {
    let result = arr[l];
    
    for (let i = l + 1; i <= r; i++) {
        result = lcm(result, arr[i]);
    }
    
    console.log(`LCM of range [${l}, ${r}] is: ${result}`);
    return result;
}

// Example usage
const arr = [1, 2, 3, 4, 5, 6];
const queries = [[1, 3], [2, 5]];

// Process all queries
queries.forEach((query, index) => {
    console.log(`Query ${index + 1}:`);
    lcmRange(arr, query[0], query[1]);
});
Query 1:
LCM of range [1, 3] is: 12
Query 2:
LCM of range [2, 5] is: 60

Optimized Segment Tree Approach

For multiple queries, we can use a Segment Tree to preprocess the array and answer queries in logarithmic time:

class SegmentTree {
    constructor(arr) {
        this.n = arr.length;
        this.tree = new Array(4 * this.n);
        this.arr = arr;
        this.build(0, this.n - 1, 1);
    }
    
    gcd(a, b) {
        return b === 0 ? a : this.gcd(b, a % b);
    }
    
    lcm(a, b) {
        return (a * b) / this.gcd(a, b);
    }
    
    build(start, end, node) {
        if (start === end) {
            this.tree[node] = this.arr[start];
            return;
        }
        
        const mid = Math.floor((start + end) / 2);
        this.build(start, mid, 2 * node);
        this.build(mid + 1, end, 2 * node + 1);
        
        this.tree[node] = this.lcm(this.tree[2 * node], this.tree[2 * node + 1]);
    }
    
    query(start, end, l, r, node) {
        // No overlap
        if (end < l || start > r) {
            return 1; // LCM identity
        }
        
        // Complete overlap
        if (l <= start && r >= end) {
            return this.tree[node];
        }
        
        // Partial overlap
        const mid = Math.floor((start + end) / 2);
        const leftLcm = this.query(start, mid, l, r, 2 * node);
        const rightLcm = this.query(mid + 1, end, l, r, 2 * node + 1);
        
        return this.lcm(leftLcm, rightLcm);
    }
    
    rangeLCM(l, r) {
        return this.query(0, this.n - 1, l, r, 1);
    }
}

// Example usage
const arr = [1, 2, 3, 4, 5, 6];
const segTree = new SegmentTree(arr);
const queries = [[1, 3], [2, 5]];

queries.forEach((query, index) => {
    const result = segTree.rangeLCM(query[0], query[1]);
    console.log(`Query ${index + 1}: LCM of range [${query[0]}, ${query[1]}] = ${result}`);
});
Query 1: LCM of range [1, 3] = 12
Query 2: LCM of range [2, 5] = 60

Complexity Analysis

Approach Time Complexity Space Complexity Best For
Naive O(Q × N × log(D)) O(1) Few queries
Segment Tree O(N + Q × log(N)) O(N) Many queries

Where Q = number of queries, N = array size, D = maximum element value

Conclusion

We explored two approaches for range LCM queries: a naive O(Q×N×log(D)) solution and an optimized segment tree approach with O(Q×log(N)) query time. The segment tree approach is preferred when dealing with multiple queries on the same array.

Updated on: 2026-03-15T23:19:01+05:30

245 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements