Subsets of size 2 or 3 with sum as multiple of 3

Last Updated : 21 Jun, 2026

Given an array arr[] of positive integers, return the count of groups of two or three such that the sum of all elements in a group is a multiple of 3.

Examples: 

Input: arr[] = {3, 6, 7, 2, 9}
Output: 8
Explanation: Groups are {3,6}, {3,9}, {9,6}, {7,2}, {3,6,9}, {3,7,2}, {7,2,6}, {7,2,9}.

Input: arr[] = {2, 1, 3, 4}
Output: 4
Explanation: Groups are {2,1}, {2,4}, {2,1,3}, {2,4,3}.

Try It Yourself
redirect icon

[Naive Approach] Using Three Nested Loops - O(n ^ 3) Time and O(1) Space

The idea is to check every possible group of size 2 and 3 from the array. For each pair or triplet, we calculate its sum and verify whether it is divisible by 3. If the condition is satisfied, we increment the count.

C++
#include <bits/stdc++.h>
using namespace std;

// Function to count valid groups
long long findGroups(vector<int> &arr)
{
    int n = arr.size();

    long long count = 0;

    // Check all possible pairs
    for (int i = 0; i < n; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            int sum = arr[i] + arr[j];

            // If sum is divisible by 3
            if (sum % 3 == 0)
            {
                count++;
            }
        }
    }

    // Check all possible triplets
    for (int i = 0; i < n; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            for (int k = j + 1; k < n; k++)
            {
                int sum = arr[i] + arr[j] + arr[k];

                // If sum is divisible by 3
                if (sum % 3 == 0)
                {
                    count++;
                }
            }
        }
    }

    return count;
}

int main()
{
    vector<int> arr = {3, 6, 7, 2, 9};

    cout << findGroups(arr);

    return 0;
}
Java
public class GFG {

    // Function to count valid groups
    static long findGroups(int[] arr)
    {
        int n = arr.length;

        long count = 0;

        // Check all possible pairs
        for (int i = 0; i < n; i++) {

            for (int j = i + 1; j < n; j++) {

                int sum = arr[i] + arr[j];

                // If sum is divisible by 3
                if (sum % 3 == 0) {
                    count++;
                }
            }
        }

        // Check all possible triplets
        for (int i = 0; i < n; i++) {

            for (int j = i + 1; j < n; j++) {

                for (int k = j + 1; k < n; k++) {

                    int sum = arr[i] + arr[j] + arr[k];

                    // If sum is divisible by 3
                    if (sum % 3 == 0) {
                        count++;
                    }
                }
            }
        }

        return count;
    }

    public static void main(String[] args)
    {

        int[] arr = { 3, 6, 7, 2, 9 };

        System.out.println(findGroups(arr));
    }
}
Python
# Function to count valid groups
def findGroups(arr):

    n = len(arr)

    count = 0

    # Check all possible pairs
    for i in range(n):

        for j in range(i + 1, n):

            summ = arr[i] + arr[j]

            # If sum is divisible by 3
            if summ % 3 == 0:
                count += 1

    # Check all possible triplets
    for i in range(n):

        for j in range(i + 1, n):

            for k in range(j + 1, n):

                summ = arr[i] + arr[j] + arr[k]

                # If sum is divisible by 3
                if summ % 3 == 0:
                    count += 1

    return count


# Driver Code
if __name__ == "__main__":
    arr = [3, 6, 7, 2, 9]

    print(findGroups(arr))
C#
using System;

class GFG {
    // Function to count valid groups
    static long findGroups(int[] arr)
    {
        int n = arr.Length;

        long count = 0;

        // Check all possible pairs
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int sum = arr[i] + arr[j];

                // If sum is divisible by 3
                if (sum % 3 == 0) {
                    count++;
                }
            }
        }

        // Check all possible triplets
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                for (int k = j + 1; k < n; k++) {
                    int sum = arr[i] + arr[j] + arr[k];

                    // If sum is divisible by 3
                    if (sum % 3 == 0) {
                        count++;
                    }
                }
            }
        }

        return count;
    }

    static void Main()
    {
        int[] arr = { 3, 6, 7, 2, 9 };

        Console.WriteLine(findGroups(arr));
    }
}
JavaScript
// Function to count valid groups
function findGroups(arr)
{
    let n = arr.length;

    let count = 0;

    // Check all possible pairs
    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            let sum = arr[i] + arr[j];

            // If sum is divisible by 3
            if (sum % 3 === 0) {
                count++;
            }
        }
    }

    // Check all possible triplets
    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            for (let k = j + 1; k < n; k++) {
                let sum = arr[i] + arr[j] + arr[k];

                // If sum is divisible by 3
                if (sum % 3 === 0) {
                    count++;
                }
            }
        }
    }

    return count;
}

// Driver Code
let arr = [ 3, 6, 7, 2, 9 ];

console.log(findGroups(arr));

Output
8

[Expected Approach] Using Combinational Approach - O(n) Time and O(1) Space

The main observation is that a number can leave only three possible remainders when divided by 3: 0, 1, or 2. We count how many numbers belong to each remainder category. Then, using valid remainder combinations whose sum becomes divisible by 3, we directly calculate the number of possible groups using combination formulas.

  • Create a frequency array c[3] to count elements having remainder 0, 1, and 2 when divided by 3.
  • Traverse the array and store the count of each remainder category in c.
  • Count valid groups of size 2. Choose any 2 elements from remainder 0. Choose one element from remainder 1 and one from remainder 2.
  • Count valid groups of size 3. All three elements from remainder 0. All three elements from remainder 1. All three elements from remainder 2.
  • Count groups containing one element each from remainder 0, 1, and 2.
  • Add all valid combinations and return the final count of groups whose sum is divisible by 3.

Consider the following dry run for better understanding : arr = {3, 6, 7, 2, 9}

  • Initial Values: n = 5, c[0] = 0, c[1] = 0, c[2] = 0, res = 0
  • Count Remainder Frequencies
    For i = 0 --> arr[0] = 3 --> 3 % 3 = 0 --> c[0] = 1
    For i = 1 --> arr[1] = 6 --> 6 % 3 = 0 --> c[0] = 2
    For i = 2 --> arr[2] = 7 --> 7 % 3 = 1 --> c[1] = 1
    For i = 3 --> arr[3] = 2 --> 2 % 3 = 2 --> c[2] = 1
    For i = 4 --> arr[4] = 9 --> 9 % 3 = 0 --> c[0] = 3
  • Groups of Size 2
    Case 1: Both elements have remainder 0, res += (3 * (3 - 1)) / 2 --> res += 3 --> res = 3
    Case 2: One element with remainder 1 and one element with remainder 2, res += 1 * 1 --> res += 1 --> res = 4
  • Groups of Size 3
    Case 3: All three elements have remainder 0, res += (3 * 2 * 1) / 6 --> res += 1 --> res = 5
    Case 4: All three elements have remainder 1, res += (1 * 0 * -1) / 6 --> res += 0 --> res = 5
    Case 5: All three elements have remainder 2, res += (1 * 0 * -1) / 6 --> res += 0 --> res = 5
    Case 6: One element each from remainder 0, 1 and 2, res += 3 * 1 * 1 --> res += 3 --> res = 8

Final answer : res = 8

C++
#include <bits/stdc++.h>
using namespace std;

// Function to count all valid groups
long long findGroups(vector<int> &arr)
{
    int n = arr.size();

    // c[0] -> count of numbers having remainder 0
    // c[1] -> count of numbers having remainder 1
    // c[2] -> count of numbers having remainder 2
    vector<long long> c(3, 0);

    // Variable to store final answer
    long long res = 0;

    // Count frequency of each remainder
    for (int i = 0; i < n; i++)
    {
        c[arr[i] % 3]++;
    }

    // Groups of size 2

    // Case 1:
    // Both elements have remainder 0
    // Example: (3, 6)
    res += (c[0] * (c[0] - 1)) / 2;

    // Case 2:
    // One element has remainder 1
    // and the other has remainder 2
    // Example: (7, 2)
    res += c[1] * c[2];

    // Groups of size 3

    // Case 3:
    // All three elements have remainder 0
    res += (c[0] * (c[0] - 1) * (c[0] - 2)) / 6;

    // Case 4:
    // All three elements have remainder 1
    res += (c[1] * (c[1] - 1) * (c[1] - 2)) / 6;

    // Case 5:
    // All three elements have remainder 2
    res += (c[2] * (c[2] - 1) * (c[2] - 2)) / 6;

    // Case 6:
    // One element from each remainder group
    // i.e. 0, 1 and 2
    res += c[0] * c[1] * c[2];

    // Return total valid groups
    return res;
}

int main()
{
    vector<int> arr = {3, 6, 7, 2, 9};

    cout << findGroups(arr);

    return 0;
}
Java
import java.util.*;

public class GFG {

    // Function to count all valid groups
    static long findGroups(int[] arr)
    {
        int n = arr.length;

        // c[0] -> count of numbers having remainder 0
        // c[1] -> count of numbers having remainder 1
        // c[2] -> count of numbers having remainder 2
        long[] c = new long[3];

        // Variable to store final answer
        long res = 0;

        // Count frequency of each remainder
        for (int i = 0; i < n; i++) {
            c[arr[i] % 3]++;
        }

        // Groups of size 2

        // Case 1:
        // Both elements have remainder 0
        // Example: (3, 6)
        res += (c[0] * (c[0] - 1)) / 2;

        // Case 2:
        // One element has remainder 1
        // and the other has remainder 2
        // Example: (7, 2)
        res += c[1] * c[2];

        // Groups of size 3

        // Case 3:
        // All three elements have remainder 0
        res += (c[0] * (c[0] - 1) * (c[0] - 2)) / 6;

        // Case 4:
        // All three elements have remainder 1
        res += (c[1] * (c[1] - 1) * (c[1] - 2)) / 6;

        // Case 5:
        // All three elements have remainder 2
        res += (c[2] * (c[2] - 1) * (c[2] - 2)) / 6;

        // Case 6:
        // One element from each remainder group
        // i.e. 0, 1 and 2
        res += c[0] * c[1] * c[2];

        // Return total valid groups
        return res;
    }

    public static void main(String[] args)
    {
        int[] arr = { 3, 6, 7, 2, 9 };

        System.out.println(findGroups(arr));
    }
}
Python
# Function to count all valid groups
def findGroups(arr):

    n = len(arr)

    # c[0] -> count of numbers having remainder 0
    # c[1] -> count of numbers having remainder 1
    # c[2] -> count of numbers having remainder 2
    c = [0] * 3

    # Variable to store final answer
    res = 0

    # Count frequency of each remainder
    for i in range(n):
        c[arr[i] % 3] += 1

    # Groups of size 2

    # Case 1:
    # Both elements have remainder 0
    # Example: (3, 6)
    res += (c[0] * (c[0] - 1)) // 2

    # Case 2:
    # One element has remainder 1
    # and the other has remainder 2
    # Example: (7, 2)
    res += c[1] * c[2]

    # Groups of size 3

    # Case 3:
    # All three elements have remainder 0
    res += (c[0] * (c[0] - 1) * (c[0] - 2)) // 6

    # Case 4:
    # All three elements have remainder 1
    res += (c[1] * (c[1] - 1) * (c[1] - 2)) // 6

    # Case 5:
    # All three elements have remainder 2
    res += (c[2] * (c[2] - 1) * (c[2] - 2)) // 6

    # Case 6:
    # One element from each remainder group
    # i.e. 0, 1 and 2
    res += c[0] * c[1] * c[2]

    # Return total valid groups
    return res


# Driver Code
if __name__ == "__main__":
    arr = [3, 6, 7, 2, 9]

    print(findGroups(arr))
C#
using System;

class GFG {
    // Function to count all valid groups
    static long findGroups(int[] arr)
    {
        int n = arr.Length;

        // c[0] -> count of numbers having remainder 0
        // c[1] -> count of numbers having remainder 1
        // c[2] -> count of numbers having remainder 2
        long[] c = new long[3];

        // Variable to store final answer
        long res = 0;

        // Count frequency of each remainder
        for (int i = 0; i < n; i++) {
            c[arr[i] % 3]++;
        }

        // Groups of size 2

        // Case 1:
        // Both elements have remainder 0
        // Example: (3, 6)
        res += (c[0] * (c[0] - 1)) / 2;

        // Case 2:
        // One element has remainder 1
        // and the other has remainder 2
        // Example: (7, 2)
        res += c[1] * c[2];

        // Groups of size 3

        // Case 3:
        // All three elements have remainder 0
        res += (c[0] * (c[0] - 1) * (c[0] - 2)) / 6;

        // Case 4:
        // All three elements have remainder 1
        res += (c[1] * (c[1] - 1) * (c[1] - 2)) / 6;

        // Case 5:
        // All three elements have remainder 2
        res += (c[2] * (c[2] - 1) * (c[2] - 2)) / 6;

        // Case 6:
        // One element from each remainder group
        // i.e. 0, 1 and 2
        res += c[0] * c[1] * c[2];

        // Return total valid groups
        return res;
    }

    static void Main()
    {
        int[] arr = { 3, 6, 7, 2, 9 };

        Console.WriteLine(findGroups(arr));
    }
}
JavaScript
// Function to count all valid groups
function findGroups(arr)
{
    let n = arr.length;

    // c[0] -> count of numbers having remainder 0
    // c[1] -> count of numbers having remainder 1
    // c[2] -> count of numbers having remainder 2
    let c = [ 0, 0, 0 ];

    // Variable to store final answer
    let res = 0;

    // Count frequency of each remainder
    for (let i = 0; i < n; i++) {
        c[arr[i] % 3]++;
    }

    // Groups of size 2

    // Case 1:
    // Both elements have remainder 0
    // Example: (3, 6)
    res += (c[0] * (c[0] - 1)) / 2;

    // Case 2:
    // One element has remainder 1
    // and the other has remainder 2
    // Example: (7, 2)
    res += c[1] * c[2];

    // Groups of size 3

    // Case 3:
    // All three elements have remainder 0
    res += (c[0] * (c[0] - 1) * (c[0] - 2)) / 6;

    // Case 4:
    // All three elements have remainder 1
    res += (c[1] * (c[1] - 1) * (c[1] - 2)) / 6;

    // Case 5:
    // All three elements have remainder 2
    res += (c[2] * (c[2] - 1) * (c[2] - 2)) / 6;

    // Case 6:
    // One element from each remainder group
    // i.e. 0, 1 and 2
    res += c[0] * c[1] * c[2];

    // Return total valid groups
    return res;
}

// Driver Code
let arr = [ 3, 6, 7, 2, 9 ];
console.log(findGroups(arr));

Output
8
Comment