C++
algorithm
least common multiple
LCM calculation
programming

C algorithm to calculate least common multiple for multiple numbers

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Computing the least common multiple for multiple integers is a standard algorithm problem with practical uses in scheduling and numerical analysis. The reliable method combines pairwise LCM with the greatest common divisor. This approach is efficient and easy to implement in C.

Mathematical Foundation

For two positive integers, LCM is defined by this identity.

lcm(a, b) = abs(a / gcd(a, b) * b)

For multiple numbers, apply this pairwise from left to right.

Implement GCD and Pairwise LCM in C

Use Euclidean algorithm for GCD and then compute LCM carefully.

c
1#include <stdio.h>
2#include <stdlib.h>
3
4long long gcd_ll(long long a, long long b) {
5    a = llabs(a);
6    b = llabs(b);
7    while (b != 0) {
8        long long t = b;
9        b = a % b;
10        a = t;
11    }
12    return a;
13}
14
15long long lcm_ll(long long a, long long b) {
16    if (a == 0 || b == 0) return 0;
17    return llabs((a / gcd_ll(a, b)) * b);
18}

This handles negative input safely by using absolute values.

Extend to Multiple Numbers

Iteratively combine values to compute global LCM.

c
1long long lcm_array(const long long *arr, int n) {
2    if (n <= 0) return 0;
3
4    long long result = arr[0];
5    for (int i = 1; i < n; i++) {
6        result = lcm_ll(result, arr[i]);
7        if (result == 0) return 0;
8    }
9    return result;
10}
11
12int main(void) {
13    long long values[] = {4, 6, 10, 14};
14    int n = sizeof(values) / sizeof(values[0]);
15
16    printf("LCM = %lld
17", lcm_array(values, n));
18    return 0;
19}

This is efficient for typical integer ranges.

Handle Overflow Risk

LCM can grow quickly. For large inputs, 64-bit overflow is possible. Add checks before multiplication or use wider integer types if available.

c
1#include <limits.h>
2
3int safe_mul_overflow(long long a, long long b) {
4    if (a == 0 || b == 0) return 0;
5    if (llabs(a) > LLONG_MAX / llabs(b)) return 1;
6    return 0;
7}

Overflow checks are important in production systems and online judges with wide constraints.

Testing Strategy

Test edge cases such as zeros, ones, repeated numbers, prime numbers, and negative numbers. Also include random tests that compare results with reference implementations in another language.

Algorithm correctness is usually straightforward, but edge handling is where most bugs appear.

Iterative Versus Recursive Style

Both iterative and recursive implementations can compute LCM for multiple numbers, but iterative style is often clearer and avoids deep call stacks for long arrays.

c
1long long lcm_recursive(const long long *arr, int n) {
2    if (n == 1) return arr[0];
3    return lcm_ll(arr[n - 1], lcm_recursive(arr, n - 1));
4}

Use recursion only when input size is controlled.

Validate with Property Checks

A robust check is that final LCM should be divisible by every non-zero input element.

c
1int validate_lcm(const long long *arr, int n, long long lcm_value) {
2    for (int i = 0; i < n; i++) {
3        if (arr[i] != 0 && lcm_value % llabs(arr[i]) != 0) {
4            return 0;
5        }
6    }
7    return 1;
8}

Property checks catch implementation mistakes during test runs.

Complexity Notes

For n numbers with average magnitude m, runtime is roughly linear in n with logarithmic factor for each GCD call. This is fast enough for most workloads when overflow is handled correctly.

Algorithmic simplicity plus correctness checks usually matters more than micro-optimizing arithmetic loops.

Input Sanitization for Real Applications

Before computing LCM, validate input length and numeric bounds. Defensive checks prevent undefined behavior in edge conditions.

c
1int has_invalid_input(const long long *arr, int n) {
2    if (arr == NULL || n <= 0) return 1;
3    return 0;
4}

Small validation helpers improve reliability when algorithm code is reused across modules.

Benchmark with Representative Inputs

If algorithm speed matters, benchmark with realistic input distributions such as many small numbers, many primes, and mixed large values. This gives a better performance picture than one synthetic case.

Use benchmark results to guide optimization effort, especially if overflow checks add measurable overhead.

Common Pitfalls

  • Multiplying before dividing by GCD and causing avoidable overflow.
  • Forgetting zero handling, which should yield LCM zero.
  • Ignoring negative input normalization.
  • Using recursion or loops without considering large input ranges.

Summary

  • Compute LCM pairwise using GCD identity.
  • Apply iteratively across the full list.
  • Add overflow checks for large input domains.
  • Validate edge cases to ensure robust behavior.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms