Problem Statement

Given an array of unsorted numbers and an integer target, find total number of triplets in it that add up to smaller than target.

Example:

Input: arr: [-1, 2, 3, 0], target = 3
Output: 2

Explanation: There are only two triplets with sum less than 3, [-1, 0, -3] and [-1, 0, 2]

Code

class Innoskrit {

    public static int findTriplets(int[] arr, int target) {
    
        Arrays.sort(arr);
        int res = 0;
        int n = arr.length;
        
        for(int i = 0; i < n - 2; i++) {
            res += findTripletsUtil(arr, i, i + 1, n, target);
        }
        
        return res;
    }
	
    private static int findTripletsUtil(int[] arr, int i, int low, int n, 
    int target) {
        int high = n - 1, res = 0;
        
        while(low < high) {
            int sum = arr[i] + arr[low] + arr[high];
            
            if(sum < target) {
                res += (high - low);
                low++;
            } else {
                high--;
            }
        }
        
        return res;
    }
	
    public static void main(String[] args) {
    
        int arr[] = new int[] {-1, 2, 3, 0};
        int target = 3;
        System.out.println(Innoskrit.findTriplets(arr, target));

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

class Innoskrit {
    
public:
    static int findTriplets(vector<int> &arr, int target) {
    	
    	sort(arr.begin(), arr.end());
    	int res = 0;
    	int n = arr.size();
    	
    	for(int i = 0; i < n - 2; i++) {
    	    res += findTripletsUtil(arr, i, i + 1, n, target);
    	}
    	return res;
    }
	
private:
    static int findTripletsUtil(vector<int> &arr, int i, int low, int n, 
    int target) {
        int high = n - 1;
        int res = 0;
        while(low < high) {
            int sum = arr[i] + arr[low] + arr[high];
            
            if(sum < target) {
                res += (high - low);
                low++;
            } else {
                high--;
            }
        }
        
        return res;
    }
};

int main() {

    vector<int> arr = {-1, 2, 3, 0};
    int target = 3;
    cout << Innoskrit::findTriplets(arr, target);
	
}
class Innoskrit:
    
    @staticmethod
    def find_triplets(arr, target):
        arr.sort()
        res, n = 0, len(arr)
        
        for i in range(0, n-1):
            res += Innoskrit.find_triplets_util(arr, i, i + 1, n, target)
        
        return res
    
    @staticmethod	
    def find_triplets_util(arr, i, low, n, target):
        high, res = n - 1, 0
        
        while low < high:
            sum = arr[i] + arr[low] + arr[high]
            if sum < target:
                res += (high - low)
                low += 1
                    
            else:
                high -= 1
        
        return res
    
if __name__ == '__main__':
    arr = [-1, 2, 3, 0]
    target = 3
    print(Innoskrit.find_triplets(arr, target))

Output:

2

Time and Space Complexity

Time Complexity: O(N2)
Sorting the array will take O(n log n) and while finding the triplets, for each element we are finding the pair in a sorted array which will add to element giving sum smaller than target and this whole process will take O(N2) time. Hence, the final time complexity is O(N2).

Space Complexity: O(1)

Slight Modification to the Problem:

Given an array of unsorted numbers and an integer target, find triplets in it that add up to smaller than target and return list of Triplets.

Example:

Input: arr: [-1, 2, 3, 0], target = 3
Output: [[-1, 0, -3], [-1, 0, 2]]

Explanation: There are only two triplets with sum less than 3, 
import java.util.*;

class Innoskrit {

    public static List<List<Integer>> findTriplets(int[] arr, int target) {
    
        Arrays.sort(arr);
        List<List<Integer>> res = new ArrayList<>();
        int n = arr.length;
        
        for(int i = 0; i < n - 2; i++) {
            findTripletsUtil(arr, i, i + 1, n, target, res);
        }
        
        return res;
    }
	
    private static List<List<Integer>> findTripletsUtil(int[] arr, int i, int low, int n, 
    int target, List<List<Integer>> res) {
        int high = n - 1;
        
        while(low < high) {
            int sum = arr[i] + arr[low] + arr[high];
            
            if(sum < target) {
                for(int x = high; x > low; x--) {
                    res.add(Arrays.asList(arr[i], arr[low], arr[x]));
                }
                low++;
            } else {
                high--;
            }
        }
        
        return res;
    }
	
    public static void main(String[] args) {
    
        int arr[] = new int[] {-1, 2, 3, 0};
        int target = 3;
        System.out.println(Innoskrit.findTriplets(arr, target));

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

class Innoskrit {
    
public:
    static vector<vector<int>> findTriplets(vector<int> &arr, int target) {
    	
    	sort(arr.begin(), arr.end());
    	vector<vector<int>> res;
    	int n = arr.size();
    	
    	for(int i = 0; i < n - 2; i++) {
    	    findTripletsUtil(arr, i, i + 1, n, target, res);
    	}
    	return res;
    }
	
private:
    static vector<vector<int>> findTripletsUtil(vector<int> &arr, int i, int low, int n, 
    int target, vector<vector<int>> &res) {
        int high = n - 1;
        
        while(low < high) {
            int sum = arr[i] + arr[low] + arr[high];
            
            if(sum < target) {
                for(int x = high; x > low; x--) {
                    res.push_back({arr[i], arr[low], arr[x]});
                }
                low++;
            } else {
                high--;
            }
        }
        
        return res;
    }
};

// Just for printing
void printResult(vector<vector<int>> &ans) {
    cout<<"[";
    for(int i = 0; i < ans.size(); i++) {
        cout<<"[";
        for(int j = 0; j < ans[i].size(); j++) {
            if(j != ans[i].size() - 1) {
                cout<<ans[i][j]<<", ";
            } else {
                cout<<ans[i][j];
            }
        }
        
        if(i != ans.size() - 1)
            cout<<"], ";
        else
            cout<<"]";
    }
    cout<<"]\n";
}

int main() {

    vector<int> arr = {-1, 2, 3, 0};
    int target = 3;
    vector<vector<int>> res = Innoskrit::findTriplets(arr, target);
    printResult(res);
	
}
class Innoskrit:
    
    @staticmethod
    def find_triplets(arr, target):
        arr.sort()
        res, n = [], len(arr)
        
        for i in range(0, n-1):
            Innoskrit.find_triplets_util(arr, i, i + 1, n, target, res)
        
        return res
    
    @staticmethod	
    def find_triplets_util(arr, i, low, n, target, res):
        high = n - 1
        
        while low < high:
            sum = arr[i] + arr[low] + arr[high]
            if sum < target:
                for x in range(high, low, -1):
                    res.append([arr[i], arr[low], arr[x]])
                low += 1
                    
            else:
                high -= 1
        
        return res
    
if __name__ == '__main__':
    arr = [-1, 2, 3, 0]
    target = 3
    print(Innoskrit.find_triplets(arr, target))

Output:

[[-1, 0, 3], [-1, 0, 2]]

Time and Space Complexity

Time Complexity: O(N2)
Sorting the array will take O(n log n) and while finding the triplets, for each element we are finding the pair in a sorted array which will add to element giving sum smaller than target and this whole process will take O(N2) time. Hence, the final time complexity is O(N2).

Space Complexity: Ignoring the size of the output array, O(1).