Reputation: 51
I'm trying to solve an algorithm question. I need to find a single integer in an array
e.g {1,1,5,5,5,3,2,2}
output should 3 because that's the only single integer there.
So far, I created an algorithm where first I sort the array and then check whether i-1 and i+1 elements are equal and if not it means I've got the single one.
The issue is; for short input it's working fine but for long inputs I receive time-outs (it takes too long to compute so my answer is not validated).
Could you give me any tips for improving the algorithm
static int lonelyinteger(int[] a) {
Arrays.sort(a);
if (a.length == 1)
return a[0];
for (int i = 0; i < a.length; ++i) {
if (i == 0) {
if (a[i + 1] != a[i])
return a[i];
} else if (i == a.length - 1) {
if (a[i] != a[i - 1])
return a[i];
} else {
if (a[i - 1] != a[i] && a[i + 1] != a[i])
return a[i];
}
}
return -1;
}
Upvotes: 4
Views: 2096
Reputation: 117
sort. then...
while (true) {
if (a[0] != a[1]) {
return a[i].
} else {
remove all a[0]s from a.
}
}
this is O(nlogn).
an O(n) solution (one w/o sort) to find all the unique integers is to have a hash and run along the array. If the number does not appear in the hash, add the number to it. If it does appear in the hash, remove that number from the hash. At the end you'll have all the unique integers in one hash. boom.
Upvotes: 0
Reputation: 9041
Is O(N^2) not considered "fast enough" for this problem?
Here I have a list of 10,000,000 elements with random pair values. In a random spot, I put the "lonely integer" 5, and O(N^2) solves it quickly without the need to sort. The algorithm stops on the first "lonely integer" it finds.
public static void main(String[] args) {
Random r = new Random();
List<Integer> ints = new ArrayList<>();
for (int i = 0; i < 10000000; i += 2) {
int randomNumber = r.nextInt(100) + 10;
ints.add(randomNumber);
ints.add(randomNumber);
}
ints.add(5); // Lonely Integer
int tempIndex = r.nextInt(ints.size());
int tempValue = ints.get(tempIndex);
// Swap duplicate integer with lonely integer
ints.set(tempIndex, ints.get(ints.size() - 1));
ints.set(ints.size() - 1, tempValue);
for (int i = 0; i < ints.size(); i++) {
boolean singleInteger = true;
for (int j = 0; j < ints.size(); j++) {
if (j == i) {
continue;
}
if (ints.get(j) == ints.get(i)) {
singleInteger = false;
break;
}
}
if (singleInteger) {
System.out.println("Single instance: " + ints.get(i));
break;
}
}
}
Results:
Single instance: 5 (about 10 - 20 seconds);
Your method about 3 seconds.
Map solution...
public static void main(String[] args) {
Random r = new Random();
List<Integer> ints = new ArrayList<>();
for (int i = 0; i < 10000000; i += 2) {
int randomNumber = r.nextInt(100) + 10;
ints.add(randomNumber);
ints.add(randomNumber);
}
ints.add(5); // Lonely Integer
int tempIndex = r.nextInt(ints.size());
int tempValue = ints.get(tempIndex);
// Swap duplicate integer with lonely integer
ints.set(tempIndex, ints.get(ints.size() - 1));
ints.set(ints.size() - 1, tempValue);
Map<Integer, Integer> counts = new HashMap<>();
for (int i : ints) {
if (counts.containsKey(i)) {
counts.put(i, counts.get(i) + 1);
} else {
counts.put(i, 1);
}
}
for (Integer key : counts.keySet()) {
if (counts.get(key) == 1) {
System.out.println("Single Instance: " + key);
}
}
}
Results:
Single Instance: 5 (about 1 - 3 seconds)
Upvotes: 1
Reputation: 2208
Start by checking that it's not Arrays.sort(a);
that's taking too long for very large inputs.
If it's not the case, you could improve your method as follows
static int lonelyinteger(int[] a) {
if (a[0] != a[1]) return a[0];
int i = 1;
while ((i < a.length - 1) && (a[i] == a[i-1] || a[i] == a[i+1])) {
i++;
}
if ((i < a.length -1) || (a[i] != a[i-1])) return a[i];
return -1;
}
Upvotes: 1
Reputation: 110
Are you sure you got the question right? The idea behind the lonely integer algorithm question, which is commonly posted on algorithm solving challenges, is that all numbers show up in pairs, except for one. From the sample that you used, it is not the case.
If all numbers are being displayed in pairs, except for one, the fastest way to find the solution is by applying XOR on all elements. Since XOR applied between two same elements cancels them, you will as a result have the lonely integer that you are looking for. The time complexity for this solution would be O(n).
Otherwise, if a number can be found in the given array more than two times, or you are using the solution you provided, the time complexity is O(n*logn).
Upvotes: 1