It's clear that if we're prepared to incur the cost of sorting then there's a simple solution - build a frequency map with sorted keys, e.g. a TreeMap, and keep removing the minimum key, which has to be in the original list, and it's double, until the map is empty or we encounter a key whose double is not in the map, in which case no solution exists.
While we can't get the global minimum without sorting we can get a series of local minima - i.e. the smallest value in a chain of doubled values. We can identify such local minima by taking each value in the original array and halving it until we can no longer find a value in the map. Once we have the local minima we can proceed as in the case of a sorted map.
static int[] doubledArray(int[] a)
{
Map<Integer, Integer> map = new HashMap<>();
for(int k : a) map.put(k, 1 + map.getOrDefault(k, 0));
int[] res = new int[a.length/2];
for(int i=0, j=0; i<a.length; i++)
{
while(map.getOrDefault(a[i], 0) > 0)
{
int k = a[i];
while(k > 0 && map.getOrDefault(k/2, 0) > 0) k /= 2;
if(map.getOrDefault(k*2, 0) == 0) return null;
res[j++] = k;
map.put(k*2, map.get(2*k)-1);
map.put(k, map.get(k)-1);
}
}
return res;
}
Test:
int[][] tests = {{8,4,1,2,2,4}, {4,8,16,2}, {2,0,1,0}, {4,3,2,1}};
for(int[] t : tests)
System.out.println(Arrays.toString(t) + " : " + Arrays.toString(doubledArray(t)));
Output:
[8, 4, 1, 2, 2, 4] : [1, 2, 4]
[4, 8, 16, 2] : [2, 8]
[2, 0, 1, 0] : [0, 1]
[4, 3, 2, 1] : null