Here's a piece of working code with your example, using HashSet:
import java.util.*;
public class Main{
public static void main(String[] args) {
int[] arr = new int[]{17, 1, 20, 4, 12, 9};
HashSet<Integer> hash = new HashSet<Integer>();
int sum = 21;
for(int i = 0; i < arr.length; i++){
hash.add(arr[i]);
}
for(int i = 0; i < arr.length; i++){
if(hash.contains(sum - arr[i])){
System.out.println(arr[i] + " and " + (sum - arr[i]));
hash.remove(arr[i]);
}
}
}
}
The complexity is O(n). The idea is to add all numbers of the array in the HashSet. Then, iterate through the array and check if, for each element arr[i], sum - arr[i] is in the HashSet. If it is, it means you have a matching pair, so you remove one of the elements of the pair to avoid repeating matches.