Check to see if any duplicate index values exist within an array? - java

So basically, I have one array, with ten values...
int[] input = new int[10];
The user controls the input to each value.
What would be a good technique to check to see if any of the values inside of the array are equal to any of the other values?
Edit:
public static void main(String[] args) {
P2 numbers = new P2();
for (int i = 0; i < numbers.input.length; i++) {
numbers.input[i] = numbers.scan.nextInt();
}
numbers.Check();
if (numbers.Check()) { System.out.println("Duplicate"); }
if (numbers.Check() == false) { System.out.println("NOT Duplicate"); }
}
public boolean Check() {
int length = input.length;
for(int i : input) {
for(int j = i + 1; j < length; j++) {
if(input[i] == input[j]) return true;
}
}
return false;
}
The codes works ask long as duplicate numbers are index-neighbors.

If you really only have ten values in the array, you're better off with a double-nested loop that breaks when it finds a duplicate.
int length = input.length;
for(int i = 0; i < length; i++) {
for(int j = i + 1; j < length; j++) {
if(intput[i] == input[j]) return true;
}
}​
If you're expecting to scale up to a large number, you're better off populating a hashset and breaking when you find a value that's already in the Hashset.
HashSet<Integer> set = new HashSet<Integer>();
for(int i : input) {
if(set.contains(i)) return true;
set.add(i);
}​

You could
compare all values in two loops (inefficient)
sort the array and then only compare adjacent values. This is more efficient, especially for longer arrays.
The first one is very easy to implement and if your array only has a length of 10, this should suffice.

If the stored int values are small non-negative values, then a BitSet might be appropriate:
BitSet set = new BitSet();
for(int i : input) {
if(set.get(i)) return true;
set.set(i);
}​
If you instead have a wide range of values, and lots of them, but a low likelihood of there being a duplicate (i.e. you expect there to be no duplicates, and simply need to confirm that), you can hash the ints, and use a BitSet(8192) of the low 13 bits of the hash (for example). That only uses roughly 1k. This can be used to easily confirm that there are no duplicates, but if it does find a hash collision, then you need to re-check with a less efficient method.

You can also sort the array and scan quickly for duplicates. Compared to building a hashset, it won't use as much memory, but will be slower.

Related

Trying to create a array with the intersection of two arrays but fails at creating array with the proper structure

So, I am trying to create 2 randomly generated arrays,(a, and b, each with 10 unique whole numbers from 0 to 20), and then creating 2 arrays with the info of the last two. One containing the numbers that appear in both a and b, and another with the numbers that are unique to a and to b. The arrays must be listed in a "a -> [1, 2, 3,...]" format. At the moment I only know how to generate the 2 arrays, and am currently at the Intersection part. The problem is, that I can create a array with the correct list of numbers, but it will have the same length of the other two, and the spaces where it shouldn't have anything, it will be filled with 0s when its supposed to create a smaller array with only the right numbers.
package tps.tp1.pack2Arrays;
public class P02ArraysExtractUniqsAndReps {
public static void main(String[] args) {
int nbr = 10;
int min = 0;
int max = 20;
generateArray(nbr, min, max);
System.out.println();
}
public static int[] generateArray(int nbr, int min, int max) {
int[] a = new int[nbr];
int[] b = new int[nbr];
int[] s = new int[nbr];
s[0] = 0;
for (int i = 0; i < a.length; i++) {
a[i] = (int) (Math.random() * (max - min));
b[i] = (int) (Math.random() * (max - min));
for (int j = 0; j < i; j++) {
if (a[i] == a[j]) {
i--;
}
if (b[i] == b[j]) {
i--;
}
}
}
System.out.println("a - > " + Arrays.toString(a));
System.out.println("b - > " + Arrays.toString(b));
for (int k = 0; k < a.length; k++) {
for (int l = 0; l < b.length; l++) {
if (a[k] == b[l]) {
s[l] = b[l];
}else {
}
}
}
System.out.println("(a ∪ (b/(a ∩ b)) - > " + Arrays.toString(s));
return null;
}
public static boolean hasValue(int[] array, int value) {
for (int i = 0; i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
}
Is there any way to create the array without the incorrect 0s? (I say incorrect because it is possible to have 0 in both a and b).
Any help/clarification is appreciated.
First, allocate an array large enough to hold the intersection. It needs to be no bigger that the smaller of the source arrays.
When you add a value to the intersection array, always add it starting at the beginning of the array. Use a counter to update the next position. This also allows the value 0 to be a valid value.
Then when finished. use Array.copyOf() to copy only the first part of the array to itself, thus removing the empty (unfilled 0 value) spaces. This works as follow assuming count is the index you have been using to add to the array: Assume count = 3
int[] inter = {1,2,3,0,0,0,0};
inter = Arrays.copyOf(inter, count);
System.out.println(Arrays.toString(inter);
prints
[1,2,3]
Here is an approach using a List
int[] b = {4,3,1,2,5,0,2};
int [] a = {3,5,2,3,7,8,2,0,9,10};
Add one of the arrays to the list.
List<Integer> list = new ArrayList<>();
for(int i : a) {
list.add(i);
}
Allocate the intersection array with count used as the next location. It doesn't matter which array's length you use.
int count = 0;
int [] intersection = new int[a.length];
Now simply iterate thru the other array.
if the list contains the value, add it to the intersection array.
then remove it from the list and increment count. NOTE - The removed value must be converted to an Integer object, otherwise, if a simple int value, it would be interpreted as an index and the value at that index would be removed and not the actual value itself (or an Exception might be thrown).
once finished the intersection array will have the values and probably unseen zeroes at the end.
for(int i = 0; i < b.length; i++) {
int val = b[i];
if (list.contains(val)) {
intersection[count++] = val;
list.remove(Integer.valueOf(val));
}
}
To shorten the array, use the copy method mentioned above.
intersection = Arrays.copyOf(intersection, count);
System.out.println(Arrays.toString(intersection));
prints
[3, 2, 5, 0, 2]
Note that it does not matter which array is which. If you reverse the arrays for a and b above, the same intersection will result, albeit in a different order.
The first thing I notice is that you are declaring your intersection array at the top of the method.
int[] s = new int[nbr];
You are declaring the same amount of space for the array regardless of the amount you actually use.
Method Arrays.toString(int []) will print any uninitialized slots in the array as "0"
There are several different approaches you can take here:
You can delay initializing the array until you have determined the size of the set you are dealing with.
You can transfer your content into another well sized array after figuring out your result set.
You could forego using Array.toString, and build the string up yourself.

Java Remove method to return new array removing occurences of integer (no arraylist)

I am trying to create a method (without using arraylist) to return a new array that removes all instances of some integer (call it x). (For example, b=[2,5,3,2,7] b.remove(2) would return [5,3,7]. This code I have been working on (one of several hours worth of different attempts) seems to work when there is one occurence of X, but not many. When there are many, it sizes the new array correctly, but does not copy the data correctly for at/after the second occurence of X.
What I am trying to do is set a counter for each time X occurs, then set a new array that has length (old array length - count variable). Then I need to shift all the data after any occurence of X left. Here's my current code:
public Sequence remove(int n) {
int count = 0;
int a = 0;
for (int z=0; z < this.values.length; z++) {
if (this.values[z] == n)
count++;
}
Sequence newSequence = new Sequence(this.values.length - count);
for (int b=0; b < this.values.length - count; b++) {
if (this.values[a] != n) {
newSequence.values[a] = this.values[a];
a++;
} else {
newSequence.values[a]=this.values[a+1];
}
}
return newSequence;
}
I think the logic for populating the new resized array should be something like this:
walk through the entire original array
if a given value be the one you want removed, do nothing
otherwise add it to the new array and also increment the index in the new array
int pos = 0; // keeps track of position in newSequence.values
for (int i=0; i < this.values.length; i++) {
if (this.values[i] != n) {
newSequence.values[pos] = this.values[i];
pos++;
}
}
To be honest I did not completely get what you trying to do. But I understood the problem and your code. I would follow these steps to solve this problem.
Iterate through the array and count the number of times n (assuming you want to remove n) occurs. This count is stored in count variable.
Create a new array with size values.length-count (here values is the array)
Copy numbers from values array to new array.
This gives a O(n) solution.

Java - Multidimensional Arrays How to test an array for all unique values

I'm trying to test a multidimensional array to see if contains any duplicate values. If it does I would like the method to return false. Otherwise I would like it to return true.
Here is my current code. Where is my logic wrong?
public static boolean isUnique(int[][] array2, int num) {
for (int i = 0; i < array2.length - 1; i++) {
for (int j = i + 1; j < array2.length; j++) {
if (array2[i] == array2[j]) {
return false;
}
}
}
return true;
}
Your current implementation is checking whether two rows are the same (this is a reference based check, rather than a value.) This means that it asks 'Are array2[i] and array2[j] the same address in memory, rather than do they contain the same things.
If you want to see whether the rows are unique you'd use array2[i].equals(array2[j]) instead of array2[i] == array2[j].
If you wanted to check for unique elements (array[i][j] != array2[i+m][j+n] where !(m == n == 0)) you'd need to iterate through both levels in a
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
// compare array2[i][j] to all other array2[m][n] here.
}
}
Right now your code is checking whether any of the arrays inside array2 are the same. array2[i] and array2[j] are both referring to arrays, because array2 is an array of arrays.
Instead, you want to look at the values inside of each of those arrays. Since you want to fail on any repeated value anywhere in the grid, you're effectively trying to flatten the structure into one collection, and check for duplicates in that.
A HashSet is the best data structure to use in this case. Traverse the entire grid, row-by-row, adding values into your new struture. If you encounter a duplicate, return false:
public static boolean isUnique(int[][] array2) {
Set<Integer> values = new HashSet<>();
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
if (!values.add(array2[i][j])) {
return false;
}
}
}
return true;
}
Some things to note here:
The set's add method will return false if you attempt to add a duplicate to the collection, so that's wrapped in an if statement for a simple, fail-fast stopping condition.
The sizes of each of the inner arrays are completely independent from the size of the outer array, so you still want to loop from 0 to the length of the array (when you're using <, you don't need the length - 1).

Randomly filling a 2d boolean array with equal amounts of both values

I'm trying to find a way to fill a 2d array of length n with boolean values randomly. The array must have an equal amount of each value if n is even, and if n is odd the extra value must be the same boolean each and every time (doesn't matter which one). Any tips on how to do this in Java? I'm currently shuffling arrays that I make with equal amounts of both values, but this isn't truly random because there will always be n/2 (or n/2+1 and n/2-1 for the odd ns) of each value.
Any advice?
Given your requirements, filling the array with the amount you need, then shuffling it, is a good solution.
Make sure to use a truly random shuffling algorithm, such as the Fisher-Yates shuffle, not the "swap a random pair a bunch of times" method. If you're using Collections.shuffle or similar, you don't need to worry about this.
Adapting the Fisher-Yates shuffle to a 2D array is probably the simplest approach.
boolean[][] array = new boolean[rows][cols];
boolean alternating = false;
Random random = new Random();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int k = random.nextInt(i * cols + j + 1);
int swapRow = k / cols;
int swapCol = k % cols;
boolean tmp = array[swapRow][swapCol];
array[swapRow][swapCol] = alternating;
array[i][j] = tmp;
alternating = !alternating;
}
}
This is pretty much a verbatim implementation of http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_.22inside-out.22_algorithm , except that we're filling the array as we go with falses and trues.
A different approach might be to randomise the position you are placing the next value rather than the value itself. You know ahead of time exactly how many of each value you are placing.
Something like:
List<Integer> indicesList = IntStream.range(0, n * n).collect(Collectors.toList());
Collections.shuffle(indicesList);
indicesList.stream().forEach(n -> array[n % size][n / size] = (n % 2 == 0));
By my understanding that should give you completely random placement of your values and an equal number of each.
Here's a real simple solution a coworker came up with. It looks to me like it would work and be truly random (please let me know if not, I have terrible intuition about that kind of thing), although it's definitely ugly. Would be pretty efficient compared to a shuffle I imagine.
public boolean[][] generateRandom2dBooleanArray(int length) {
int numFalses = (length*length)/2;
int numTrues = (length*length)/2;
if ((length*length)%2!=0) numTrues++;
boolean[][] array = new boolean[length][length];
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (Math.random() > 0.5) {//Or is it >= 0.5?
if (numTrues >= 0) {
array[i][j] = true;
numTrues--;
} else {
//Since boolean arrays are false by default, you could probably just break here to get the right anser, but...
array[i][j] = false;
numFalses--;
}
} else {
if (numFalses >= 0) {
array[i][j] = false;
numFalses--;
} else {
array[i][j] = true;
numTrues--;
}
}
}
}
}
return array;
}

finding the number of pairs of numbers in an array that add up to a number

I am trying to come up with a program that will search inside of an array that is given a length by the user that picks out whether there is a pair of numbers that sum to 7. The idea is that if there is k amount of dice being thrown, how many pairs of numbers out of those dice thrown add up to 7. So far this is all that I could come up with but I am very stuck.
This is the driver class for the program. I have to write a class that will make this driver function properly.
import java.util.Scanner;
public class SevenDriver{
public static void main(String[] args){
System.out.println("Enter number of dice to toss");
Scanner s = new Scanner(System.in);
int diceCount = s.nextInt();
SevenTally t = new SevenTally(diceCount);
int experiments = 1000000;
int wins = 0;
for(int j = 0; j < experiments; j++)
if(t.experiment()) wins++;
System.out.println((double)wins/experiments);
}
}
This is what I have so far. It does not currently work or compile. I am just looking for some ideas to get me going. Thanks!
public class SevenTally{
private int diceCount;
public SevenTally(int die){
diceCount = die;
}
public int genDice(){
return 1 + (int)(Math.random()*6);
}
public boolean experiment(){
boolean[] nums = new boolean[diceCount];
int ranNum;
int sum = 7;
for(int i = 0; i < nums.length; i++){
ranNum = genDice();
if (nums[ranNum] == sum){
return true;
}
}
int left = 0;
int right = nums.length - 1;
while(left<right){
int tempSum = nums[left] + nums[right];
if(tempSum == 7){
return true;
}
else if(tempSum>7){
right--;
}
return false;
}
}
First populate your array of length k with random int in [1;6]
The number of possible pairs in an array of length k is the number of 2-combinations in the array, which is (k-1)*k/2 (http://en.wikipedia.org/wiki/Combination)
You can test all the possible pairs (i,j) in your array like so:
int win = 0;
int tally = 7;
for(int i=0; i<k-1; i++){
for(int j=i+1; j<k; j++){
if(array[i]+array[j] == tally){
win++;
}
}
}
What this does is that it sets the first element of the pair to be the first element of the array, and sums it with the other elements one after the other.
It pairs array[0] with array[1] to array[k-1] at the first pass of the i for loop, that's k pairs.
Then k-1 pairs at second pass, and so on.
You end up with (k)+(k-1)+(k-2)+...+1 pairs, and that's exactly (k-1)*k/2 pairs.
done =]
edit: sorry, haven't read the whole thing. the method experiment() is supposed to return a boolean. you can return win>0?true:false; for example...
This Wiki page has some algorithms to do that. Its not a trivial problem...
You're generating a random number in ranNum, and then using it as an index into the array nums. Meanwhile, nums never gets filled, so no matter which box you index into, it never contains a 7.
What you want to do, if I understand your problem correctly, is fill each space in the array with the result of a die roll, then compare every two positions (rolls) to see if they sum to seven. You can do that using a nested for loop.
Essentially, you want to do this: (written in pseudocode as I'm not a java programmer)
int[] results[numrolls]
for (count = 0 to numrolls-1) { results[numrolls]=dieRoller() }
for (outer = 0 to numrolls-2)
for (inner = outer+1 to numrolls-1)
if (results[outer] + results[inner] == 7) return true
return false;
However, in this case there's an even easier way. You know that the only ways to get a sum of 7 on 2d6 are (1,6),(2,5),(3,4),(4,3),(5,2),(6,1). Set up a 6-length boolean array, roll your dice, and after each roll set res[result] to true. Then return (1-based array used for simplicity) ( (res[1] && res[6]) || (res[2] && res[5]) || (res[3] && res[4]) ).
ArrayIndexOutOfBoundsException means you are trying to access an element of the array that hasn't been allocated.
In your code, you create a new array d of length diceCount, but then you genDice() on always 6 elements.

Categories