Reputation: 2033
I have two integer array each of same size say n ( n is variable, so I can have two arrays of size say 4 or 5 or 6 etc ) and the range of values that each digit can take is in the range of 0-9. Example
Integer[] one = {1,9,3,4}
Integer[] two = {1,1,9,3}
Now, I want to compare array one & two such that 1) I can get the count of numbers of elements which are same and at the same position. 2) I can get the count of number which are same but not at the same position .
The approach I have taken is
For (1) Iterate through array one and for each index i check one[i] == two[i]
. - simple .
For (2) Iterate over both the arrays and for i != j
see if the elements are same , if same mark them with -1 to avoid future conflicts.
for(int i =0;i<one.length;i++){
for(int j=0;j<two.length;j++){
if(i != j && one[i] != -1 && two[j] !=-1)){
if(one[i] == two[j]){
whiteCount++
one[i] = -1;
two[j] = -1;
}
}
}
}
Question : Now I want to know if there is a faster way to do the same thing ? Esp. calculating the (2)nd part of the problem. This is a basic comparison method to get black and white pegs calculation for Mastermind board game . Thanks Shakti
UPDATE 1: 1) Rudi's suggestion changed Integer[] to int[]
2) Used Dave Challis's solution Change in performance for 7776 X 7776 calculations
OLD 46950 ms
NEW 42887 ms
Upvotes: 7
Views: 6072
Reputation: 533510
To get the count of the number of number which are the same, but at different positions, you can do this.
public static long[] encode(int... nums) {
long[] ret = new long[nums.length];
for (int i = 0; i < nums.length; i++) {
ret[i] = ((long) nums << 32) + i;
}
Arrays.sort(ret);
}
// encode both arrays and do a merge sort, skipping matches which have the same index.
This is an O(n log N) operation.
You could move the one[i] != -1
check out so it can skip that value.
int[] one = {1,9,3,4}; // Using int is faster and clearer.
int[] two = {1,1,9,3};
for (int i = 0; i < one.length; i++){
if (one[i] == -1) continue;
for (int j = 0; j < two.length; j++){
if (one[i] == two[j] && i != j && two[j] != -1) {
whiteCount++
one[i] = -1;
two[j] = -1;
}
}
}
Putting the one[i] == two[j]
first improves performance because it will usually be false so the other things don't need to be checked.
Upvotes: 3
Reputation: 3906
The solution below is O(2N), doesn't use any additional libraries, and doesn't modify the initial arrays.
It loops through both arrays once to get a count of integers at the same position. While it does this, it builds up a count of each number in the 2nd array (and stores in the counts
array).
It then loops through the first array again, getting the total number of times each number was found in the 2nd array:
final Integer[] one = {1,9,3,4};
final Integer[] two = {1,1,9,3};
int samePositionCount = 0;
int sameNumberCount = 0;
// tracks number of times an int is in the 2nd array
final Integer[] counts = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
for (int i = 0; i < one.length; i++) {
if (one[i].equals(two[i])) {
samePositionCount++;
counts[one[i]] = -1; // mark as seen in same position count
} else if (counts[two[i]] != -1) {
counts[two[i]]++;
}
}
for (int i : one) {
if (counts[i] > 0) {
sameNumberCount += counts[i];
counts[i] = 0; // avoid adding twice
}
}
System.out.println(samePositionCount + " " + sameNumberCount);
Prints:
1 2
Upvotes: 3
Reputation: 12972
Although this probably isn't exactly what your looking for, we could reduce the number of operations significantly with a very simple change.
From
Integer[] one = {1,9,3,4}
Integer[] two = {1,1,9,3}
to
int[] one = {1,9,3,4}
int[] two = {1,1,9,3}
This will speed up the process by a small amount, but not by optimizing the sorting/searching logic itself. All we're doing there is removing the auto-boxing and auto-unboxing operations. If however your doing this on a very large scale then this can make a substantial difference.
Upvotes: 5
Reputation: 403
Why not use the existing utility methods for comparing the aaarays. They are definitely faster. You can check the implemetation of "equals" method and confirm.
import java.util.Arrays;
class Test {
public static void main(String[] args) {
int inarr1[] = {1, 2, 3};
int inarr2[] = {1, 2, 3};
Object[] arr1 = {inarr1};
Object[] arr2 = {inarr2};
if (Arrays.deepEquals(arr1, arr2))
System.out.println("Same");
else
System.out.println("Not same");
}
}
Upvotes: 0