Open In App

CSES Solutions – Sum of Four Values

Last Updated : 28 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

You are given an array arr[] of N integers, and your task is to find four values (at distinct positions) whose sum is X.

Note: If there are multiple answers, print any one of them.

Examples:

Input: N = 8, X = 15, arr[] = {3, 2, 5, 8, 1, 3, 2, 3}
Output: 2 4 6 7
Explanation: Elements at position 2, 4, 6 and 7 are: 2, 8, 3 and 2 respectively. Total sum = 2 + 8 + 3 + 2 = 15

Input: N = 6, X = 20, arr[] = {3, 4, 5, 6, 7, 8}
Output: 1 2 3 6
Explanation: Elements at position 1, 2, 3 and 6 are: 3, 4, 5 and 8 respectively. Total sum = 3 + 4 + 5 + 8 = 20

Approach: To solve the problem, follow the below idea:

The problem is similar to Sum of Three Values except that we need to find four indices whose values which sum up to X. This can be done by maintain an extra pointer for the fourth index.

The problem can be solved using Sorting and Two Pointer approach. Store pair of values and index of arr[] in a 2D vector, say vec[][]. Sort vec[][] in ascending order of the values. Iterate two nested loops, outer loop ptr1 from 0 to N – 3, for the first value and inner loop ptr2 from (ptr1 + 1) to N – 2. We assume that vec[ptr1][0] is the first value and vec[ptr2][0] is the second value and now we need to search for the third and fourth value. For the third and fourth value, we can use two pointers(ptr3 and ptr4) on the ends of the remaining subarray (ptr3 = ptr2 + 1, ptr4 = N – 1). Let’s say the sum of these four values is currentSum = vec[ptr1][0] + vec[ptr2][0] + vec[ptr3][0] + vec[ptr4][0]. Now, we can have three cases:

  • Case 1: currentSum = X, we got the answer so print vec[ptr1][1], vec[ptr2][1], vec[ptr3][1] and vec[ptr4][1].
  • Case 2: currentSum < X, this means we want to increase the sum of four values. Since we have assumed that vec[ptr1][0] is the first value and vec[ptr2][0] is the second value, we cannot change ptr1 and ptr2. So, the only way to increase the sum is to move ptr3 forward, that is ptr3 = ptr3 + 1.
  • Case 3: currentSum > X, this means we want to decrease the sum of four values. Since we have assumed that vec[ptr1][0] is the first value and vec[ptr2][0] is the second value, we cannot change ptr1 and ptr2. So, the only way to decrease the sum is to move ptr4 backward, that is ptr4 = ptr4 – 1.

We keep on moving ptr3 and ptr4 closer till ptr3 < ptr4. If we didn’t get any valid quadruplet ptr1, ptr2, ptr3 and ptr4 such that vec[ptr1][0] + vec[ptr2][0] + vec[ptr3][0] + vec[ptr4][0] = X, it means that our assumption that vec[ptr1][0] is the first value and vec[ptr2][0] is the second value is wrong, so we will shift ptr2 to ptr2 + 1 and assume that vec[ptr2][0] is the second value. Again, start finding a valid quadruplet with sum = X. After ptr2 reaches then end, we shift ptr1 by 1 and again start with ptr2 = ptr1 + 1.

If after all the cases we don’t get any answer, then it is impossible to have sum = X.

Step-by-step algorithm:

  • Maintain a 2D vector, say vec[][] to store values along with their indices.
  • Sort vec[][] in ascending order of the values.
  • Iterate ptr1 from 0 to N – 3,
    • Iterate ptr2 from ptr+1 to N – 2,
      • Declare two pointers ptr3 = ptr3 + 1 and ptr4 = N – 1.
      • Store the sum of vec[ptr1][0] + vec[ptr2][0] + vec[ptr3][0] + vec[ptr4][0] as currentSum.
      • If currentSum = X, then print the three indices as vec[ptr1][1], vec[ptr2][1], vec[ptr3][1] and vec[ptr4][1].
      • Else if currentSum < X, move ptr3 to ptr3 + 1.
      • Else if currentSum > X, move ptr4 to ptr4 – 1.
  • After all the iterations, if no triplet is found whose sum = X, then print “IMPOSSIBLE”.

Below is the implementation of the algorithm:

C++
#include <bits/stdc++.h>
#define ll long long int

using namespace std;

// function to find a quadruplet whose sum = X
void solve(vector<ll>& arr, ll X, ll N)
{
    // vector to store the values along with their indices
    vector<vector<ll>> vec(N, vector<ll>(2));

    for (int i = 0; i < N; i++) {
        vec[i][0] = arr[i];
        vec[i][1] = i + 1;
    }

    // Sort the vector in increasing order of the values
    sort(vec.begin(), vec.end());

    // Iterate for all possible values of first element
    for (ll ptr1 = 0; ptr1 < N - 3; ptr1++) {

        // Iterate for all possible values of second element
        for (ll ptr2 = ptr1 + 1; ptr2 < N - 2; ptr2++) {

            // Maintain two pointers for the third and
            // fourth element
            ll ptr3 = ptr2 + 1;
            ll ptr4 = N - 1;
            while (ptr3 < ptr4) {
                ll currentSum = vec[ptr1][0] + vec[ptr2][0]
                                + vec[ptr3][0]
                                + vec[ptr4][0];

                // If current sum is equal to X, then we
                // have found a quadruplet whose sum = X
                if (currentSum == X) {
                    cout << vec[ptr1][1] << " "
                         << vec[ptr2][1] << " "
                         << vec[ptr3][1] << " "
                         << vec[ptr4][1] << "\n";
                    return;
                }

                // Decrease the currentSum by moving ptr4 to
                // ptr4 - 1
                else if (currentSum > X) {
                    ptr4--;
                }

                // Increase the currentSum by moving ptr3 to
                // ptr3 + 1
                else if (currentSum < X) {
                    ptr3++;
                }
            }
        }
    }
    // If no quadruplet has sum = X, print "IMPOSSIBLE"
    cout << "IMPOSSIBLE";
}

int main()
{
    // Sample Input
    ll N = 6, X = 20;
    vector<ll> arr = { 3, 4, 5, 6, 7, 8 };

    solve(arr, X, N);
    // your code goes here
    return 0;
}
Java
import java.util.*;

public class Main {
    // Function to find a quadruplet whose sum = X
    static void GFG(ArrayList<Long> arr, long X, int N) {
        ArrayList<ArrayList<Long>> vec = new ArrayList<>(N);
        for (int i = 0; i < N; i++) {
            vec.add(new ArrayList<>(Arrays.asList(arr.get(i), (long) (i + 1))));
        }
        // Sort the ArrayList in increasing order of the values
        Collections.sort(vec, Comparator.comparingLong(a -> a.get(0)));
        for (int ptr1 = 0; ptr1 < N - 3; ptr1++) {
            // Iterate for all possible values of the second element
            for (int ptr2 = ptr1 + 1; ptr2 < N - 2; ptr2++) {
                int ptr3 = ptr2 + 1;
                int ptr4 = N - 1;
                while (ptr3 < ptr4) {
                    long currentSum = vec.get(ptr1).get(0) + vec.get(ptr2).get(0)
                            + vec.get(ptr3).get(0) + vec.get(ptr4).get(0);
                    // If current sum is equal to X
                    // then we have found a quadruplet whose sum = X
                    if (currentSum == X) {
                        System.out.println(vec.get(ptr1).get(1) + " "
                                + vec.get(ptr2).get(1) + " "
                                + vec.get(ptr3).get(1) + " "
                                + vec.get(ptr4).get(1));
                        return;
                    }
                    // Decrease the currentSum by moving the ptr4 to ptr4 - 1
                    else if (currentSum > X) {
                        ptr4--;
                    }
                    else if (currentSum < X) {
                        ptr3++;
                    }
                }
            }
        }
        // If no quadruplet has sum = X
        // print "IMPOSSIBLE"
        System.out.println("IMPOSSIBLE");
    }
    public static void main(String[] args) {
        // Sample Input
        int N = 6;
        long X = 20;
        ArrayList<Long> arr = new ArrayList<>(Arrays.asList(3L, 4L, 5L, 6L, 7L, 8L));
        GFG(arr, X, N);
    }
}
Python3
# function to find a quadruplet whose sum = X
def solve(arr, X, N):
    # list to store the values along with their indices
    vec = [[arr[i], i + 1] for i in range(N)]

    # Sort the list in increasing order of the values
    vec.sort()

    # Iterate for all possible values of first element
    for ptr1 in range(N - 3):
        # Iterate for all possible values of second element
        for ptr2 in range(ptr1 + 1, N - 2):
            # Maintain two pointers for the third and fourth element
            ptr3 = ptr2 + 1
            ptr4 = N - 1
            while ptr3 < ptr4:
                currentSum = vec[ptr1][0] + vec[ptr2][0] + vec[ptr3][0] + vec[ptr4][0]

                # If current sum is equal to X, then we have found a quadruplet whose sum = X
                if currentSum == X:
                    print(vec[ptr1][1], vec[ptr2][1], vec[ptr3][1], vec[ptr4][1])
                    return
                # Decrease the currentSum by moving ptr4 to ptr4 - 1
                elif currentSum > X:
                    ptr4 -= 1
                # Increase the currentSum by moving ptr3 to ptr3 + 1
                elif currentSum < X:
                    ptr3 += 1

    # If no quadruplet has sum = X, print "IMPOSSIBLE"
    print("IMPOSSIBLE")


# Sample Input
N = 6
X = 20
arr = [3, 4, 5, 6, 7, 8]

solve(arr, X, N)
C#
using System;

class Program
{
    public static void Solve(int[] arr, int X, int N)
    {
        // Array to store the values along with their indices
        var vec = new (int Value, int Index)[N];
        for (int i = 0; i < N; i++)
        {
            vec[i] = (arr[i], i + 1);
        }

        // Sort the array in increasing order of the values
        Array.Sort(vec, (a, b) => a.Value.CompareTo(b.Value));

        // Iterate for all possible values of the first element
        for (int ptr1 = 0; ptr1 < N - 3; ptr1++)
        {
            // Iterate for all possible values of the second element
            for (int ptr2 = ptr1 + 1; ptr2 < N - 2; ptr2++)
            {
                // Maintain two pointers for the third and fourth element
                int ptr3 = ptr2 + 1;
                int ptr4 = N - 1;
                while (ptr3 < ptr4)
                {
                    int currentSum = vec[ptr1].Value + vec[ptr2].Value + vec[ptr3].Value + vec[ptr4].Value;

                    // If current sum is equal to X, then we have found a quadruplet whose sum = X
                    if (currentSum == X)
                    {
                        Console.WriteLine($"{vec[ptr1].Index} {vec[ptr2].Index} {vec[ptr3].Index} {vec[ptr4].Index}");
                        return;
                    }
                    // Decrease the currentSum by moving ptr4 to ptr4 - 1
                    else if (currentSum > X)
                    {
                        ptr4 -= 1;
                    }
                    // Increase the currentSum by moving ptr3 to ptr3 + 1
                    else if (currentSum < X)
                    {
                        ptr3 += 1;
                    }
                }
            }
        }

        // If no quadruplet has sum = X, print "IMPOSSIBLE"
        Console.WriteLine("IMPOSSIBLE");
    }

    static void Main(string[] args)
    {
        int N = 6;
        int X = 20;
        int[] arr = { 3, 4, 5, 6, 7, 8 };

        Solve(arr, X, N);
    }
}
JavaScript
// function to find a quadruplet whose sum = X
function solve(arr, X, N) {
    let vec = new Array(N).fill(0).map(() => new Array(2));

    for (let i = 0; i < N; i++) {
        vec[i][0] = arr[i];
        vec[i][1] = i + 1;
    }

    // Sort the vector in increasing order of the values
    vec.sort((a, b) => a[0] - b[0]);

    // Iterate for all possible values of first element
    for (let ptr1 = 0; ptr1 < N - 3; ptr1++) {
        // Iterate for all possible values of second element
        for (let ptr2 = ptr1 + 1; ptr2 < N - 2; ptr2++) {
            // Maintain two pointers for the third and fourth element
            let ptr3 = ptr2 + 1;
            let ptr4 = N - 1;
            while (ptr3 < ptr4) {
                let currentSum = vec[ptr1][0] + vec[ptr2][0] + vec[ptr3][0] + vec[ptr4][0];

                // If current sum is equal to X, then we have found a quadruplet whose sum = X
                if (currentSum === X) {
                    console.log(vec[ptr1][1], vec[ptr2][1], vec[ptr3][1], vec[ptr4][1]);
                    return;
                } else if (currentSum > X) {
                    ptr4--;
                } else if (currentSum < X) {
                    ptr3++;
                }
            }
        }
    }
    // If no quadruplet has sum = X, print "IMPOSSIBLE"
    console.log("IMPOSSIBLE");
}

// Sample Input
let N = 6, X = 20;
let arr = [3, 4, 5, 6, 7, 8];

solve(arr, X, N);

Output
1 2 3 6

Time Complexity: O(N * N * N), where N is the size of input array arr[].
Auxiliary Space: O(1)

Approach2 (Using Map)

Create a function. We use an unordered_map pairSums to store the sums of pairs of elements and their indices. Now we iterate over all pairs of elements in the input array and store their sums in the Hashmap. Then, we iterate over all pairs of sums in the Hashmap and check if the complement exists in the Hashmap. If it exist, and all the indices are distinct, we return the indices of the four values.

Steps by steps Implementation of above Approach

  • Create a hashmap to store the sums of all pairs of elements.
  • Iterate over all pairs of elements in the input array and store their sums along with their indices in the hashmap.
  • Iterate over all pairs of sums in the hashmap and check if the complement of each pair exists in the hashmap.
  • If exist return the indices of the four values

Below is Implementation of above approach

C++
#include <iostream>
#include <unordered_map>
#include <vector>

using namespace std;

vector<int> findFourSum(const vector<int>& arr, int target)
{
    // Map to store sums of pairs and their indices
    unordered_map<int, pair<int, int> > pairSums;

    // Iterate over all pairs of elements and store their
    // sums
    for (int i = 0; i < arr.size(); ++i) {
        for (int j = i + 1; j < arr.size(); ++j) {
            int sum = arr[i] + arr[j];
            pairSums[sum] = { i, j };
        }
    }

    // Iterate over all pairs of sums and check for the
    // complement
    for (auto it = pairSums.begin(); it != pairSums.end();
         ++it) {
        int sum = it->first;
        auto& indices = it->second;

        int complement = target - sum;
        if (pairSums.count(complement)) {
            auto& complementIndices = pairSums[complement];
            // Ensure that all indices are distinct
            if (indices.first != complementIndices.first
                && indices.first != complementIndices.second
                && indices.second != complementIndices.first
                && indices.second
                       != complementIndices.second) {
                return { indices.first, indices.second,
                         complementIndices.first,
                         complementIndices.second };
            }
        }
    }

    // If no such combination exists
    return {};
}

int main()
{
    vector<int> arr = { 1, 2, 3, 4, 5, 6, 7, 8 };
    int target = 20;

    vector<int> indices = findFourSum(arr, target);
    if (!indices.empty()) {
        cout << "Indices of the four numbers: ";
        for (int index : indices) {
            cout << index << " ";
        }
        cout << endl;
    }
    else {
        cout << "No combination of four numbers found."
             << endl;
    }

    return 0;
}

// Note :Since the map data structure doesn't guarantee the
// order of its elements,
// the order of the pairs stored in the map could vary
// between different executions or between different
// languages.
Java
import java.util.*;

public class Main {
    public static void main(String[] args)
    {
        int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8 };
        int target = 20;

        List<Integer> indices = findFourSum(arr, target);
        if (!indices.isEmpty()) {
            System.out.println(
                "Indices of the four numbers: " + indices);
        }
        else {
            System.out.println(
                "No combination of four numbers found.");
        }
    }

    public static List<Integer> findFourSum(int[] arr,
                                            int target)
    {
        // Map to store sums of pairs and their indices
        Map<Integer, List<Integer> > pairSums
            = new HashMap<>();

        // Iterate over all pairs of elements and store
        // their sums
        for (int i = 0; i < arr.length; ++i) {
            for (int j = i + 1; j < arr.length; ++j) {
                int sum = arr[i] + arr[j];
                pairSums.put(sum, Arrays.asList(i, j));
            }
        }

        // Iterate over all pairs of sums and check for the
        // complement
        for (Map.Entry<Integer, List<Integer> > entry :
             pairSums.entrySet()) {
            int sum = entry.getKey();
            List<Integer> indices = entry.getValue();
            int complement = target - sum;
            if (pairSums.containsKey(complement)) {
                List<Integer> complementIndices
                    = pairSums.get(complement);
                // Ensure that all indices are distinct
                if (!indices.contains(
                        complementIndices.get(0))
                    && !indices.contains(
                        complementIndices.get(1))) {
                    return new ArrayList<>(Arrays.asList(
                        indices.get(0), indices.get(1),
                        complementIndices.get(0),
                        complementIndices.get(1)));
                }
            }
        }

        // If no such combination exists
        return new ArrayList<>();
    }
}
Python3
def find_four_sum(arr, target):
    # Dictionary to store sums of pairs and their indices
    pair_sums = {}

    # Iterate over all pairs of elements and store their sums
    for i in range(len(arr)):
        for j in range(i + 1, len(arr)):
            pair_sum = arr[i] + arr[j]
            pair_sums[pair_sum] = [i, j]

    # Iterate over all pairs of sums and check for the complement
    for sum_val, indices in pair_sums.items():
        complement = target - sum_val
        if complement in pair_sums:
            complement_indices = pair_sums[complement]
            # Ensure that all indices are distinct
            if (indices[0] not in complement_indices and indices[1] not in complement_indices):
                return indices + complement_indices

    # If no such combination exists
    return []


arr = [1, 2, 3, 4, 5, 6, 7, 8]
target = 20

indices = find_four_sum(arr, target)
if indices:
    print("Indices of the four numbers:", " ".join(map(str, indices)))
else:
    print("No combination of four numbers found.")
JavaScript
function findFourSum(arr, target) {
    // Map to store sums of pairs and their indices
    const pairSums = new Map();

    // Iterate over all pairs of elements and store their sums
    for (let i = 0; i < arr.length; ++i) {
        for (let j = i + 1; j < arr.length; ++j) {
            const sum = arr[i] + arr[j];
            pairSums.set(sum, [i, j]);
        }
    }

    // Iterate over all pairs of sums and check for the complement
    for (const [sum, indices] of pairSums.entries()) {
        const complement = target - sum;
        if (pairSums.has(complement)) {
            const complementIndices = pairSums.get(complement);
            // Ensure that all indices are distinct
            if (!indices.includes(complementIndices[0]) &&
                !indices.includes(complementIndices[1])) {
                return [...indices, ...complementIndices];
            }
        }
    }

    // If no such combination exists
    return [];
}

const arr = [1, 2, 3, 4, 5, 6, 7, 8];
const target = 20;

const indices = findFourSum(arr, target);
if (indices.length !== 0) {
    console.log("Indices of the four numbers:", indices.join(" "));
} else {
    console.log("No combination of four numbers found.");
}


// Note :Since the map data structure doesn't guarantee 
// the order of its elements, 
//the order of the pairs stored in the map could vary between 
// different executions or between different languages.

Output
Indices of the four numbers: 6 7 1 2 

Time Complexity: O(n^2)

Space Complexity: O(n^2)




Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads