Reputation: 159
I have the below code which is aimed at finding out a duplicate element in an array and printing it with its count.
I have used the below approach to solve the problem.
For calculating the length I am using my own version of code.
It o/ps 5 4 2 3
which is correct but I want to know if we can still refine this code.
Please suggest best approach, condition is that there should not be any build in method/functions usage.
package codingpractice;
public class DuplicateCount {
public static void main(String argsp[]) throws Exception {
int array[] = { 5, 1, 2, 5, 3, 2, 2, 5, 5 };
DuplicateCount hw = new DuplicateCount();
int length = hw.length(array);
hw.duplicates(array, length);
}
public void duplicates(int array[], int length) throws Exception {
int end =length, dupCount = 0;
//copying to another array for later comparison
int[] aarray = new int[length];
for (int i = 0; i < end; i++) {
aarray[i] = array[i];
}
//finding duplicates and removing the same
for (int i = 0; i < end; i++) {
for (int j = i + 1; j < end; j++) {
if (array[i] == array[j]) {
int shiftLeft = j;
for (int k = j + 1; k < end; k++, shiftLeft++) {
array[shiftLeft] = array[k];
}
end--;
j--;
}
}
}
//copying non duplicates to another array
int[] tarray = new int[end];
for (int i = 0; i < end; i++) {
tarray[i] = array[i];
}
//Printing duplicates and there counts, comparing original array and non duplicate array
for (int i = 0; i < length(tarray); i++) {
dupCount = 0;
for (int j = 0; j < length; j++) {
if (tarray[i] == aarray[j]) {
dupCount++;
}
}
if (dupCount > 1) {
System.out.println(tarray[i] + " " + dupCount);
}
}
}
//length of array- not using inbuild function
int length(int array[]) throws Exception {
int count = 0;
int temp = 0;
try {
while (true) {
count++;
temp = array[count];
}
} catch (Exception e) {
return count;
}
}
}
Upvotes: 0
Views: 1020
Reputation: 691715
Much easier technique:
Map<Integer, Integer> map = new HashMap<>();
for (int i : array) {
Integer count = map.get(i);
if (count == null) {
map.put(i, 1);
}
else {
map.put(i, count.intValue() + 1);
}
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if (entry.getValue() > 1) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
}
For the fun of it, here's a Java 8 equivalent:
Map<Integer, Integer> map = new HashMap<>();
for (int i : array) {
map.compute(i, (k, v) -> (v == null) ? 1 : v + 1);
}
map.entrySet().stream()
.filter(e -> e.getValue() > 1)
.forEach(e -> System.out.println(e.getKey() + " : " + e.getValue()));
The map.compute()
call could also be replaced by
map.merge(i, 1, Integer::sum);
Upvotes: 3
Reputation: 61148
Just to complement JB Nizet's Java 7 solution. Here is a Java 8 solution:
public static void main(final String[] args) throws Exception {
final int[] ints = {1, 1, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 0, 0, 0};
final Map<Integer, Integer> count = IntStream.of(ints).
boxed().collect(HashMap::new, (map, i) -> {
map.merge(i, 1, (j, k) -> j + k);
}, HashMap::putAll);
//to print out
count.forEach((i, c) -> {System.out.println( i + " has a count of " + c);});
}
Output:
0 has a count of 3
1 has a count of 2
2 has a count of 1
3 has a count of 2
4 has a count of 2
5 has a count of 1
6 has a count of 1
7 has a count of 1
8 has a count of 1
9 has a count of 1
Upvotes: 2
Reputation: 1605
Using indices, create an empty array. Run on your array and increase the corresponding value at the index each time you run on it.
In your example:
int[] source = { 5, 1, 2, 5, 3, 2, 2, 5, 5 };
int[] counts = new int[6];
for (int i : source) {
counts[i]++;
}
Then your can run on the counts and you will get each element (array index) and its count (array value).
Upvotes: 1