Get all subsets of a set - java

import java.util.ArrayList;
public class Subset { //Generate all subsets by generating all binary numbers
public static ArrayList<ArrayList<Integer>> getSubsets2(ArrayList<Integer> set) {
ArrayList<ArrayList<Integer>> allsubsets =
new ArrayList<ArrayList<Integer>>();
int max = 1 << set.size(); //there are 2 power n
for (int i = 0; i < max; i++) {
ArrayList<Integer> subset = new ArrayList<Integer>();
int index = 0;
while (i > 0) {
if ((i & 1) > 0) {
subset.add(set.get(index)); //Add elements to a new ArrayList
}
i >>= 1;
index++;
}
allsubsets.add(subset);
}
return allsubsets;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<Integer> set = new ArrayList<Integer>(); //Create an ArrayList
set.add(1);
set.add(2);
System.out.println(getSubsets2(set));
}
}
The result should be [[],[1],[2],[1,2]]
But I can't get the result, the exception is as follows:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

Your while loop is incorrect.
Made slightly more succinct with a for-loop:
import java.util.ArrayList;
public class Subset { //Generate all subsets by generating all binary numbers
public static ArrayList<ArrayList<Integer>> getSubsets2(ArrayList<Integer> set) {
ArrayList<ArrayList<Integer>> allsubsets =
new ArrayList<ArrayList<Integer>>();
int max = 1 << set.size(); //there are 2 power n different subsets
for (int i = 0; i < max; i++) {
ArrayList<Integer> subset = new ArrayList<Integer>();
for (int j = 0; j < set.size(); j++) {
if (((i >> j) & 1) == 1) {
subset.add(set.get(j));
}
}
allsubsets.add(subset);
}
return allsubsets;
}
public static void main(String[] args) {
ArrayList<Integer> set = new ArrayList<Integer>(); //Create an ArrayList
set.add(1);
set.add(2);
System.out.println(getSubsets2(set));
}
}
Bear in mind that the subset operation is exponential, so you'll get a very large number of elements. The implementation above will only work with about 32 input elements, as that yields 2^32 output subsets, which will very easily run you over the limit of an array...

Your problem appears to be in your loop. If you look at it:
for (int i = 0; i < max; i++) {
ArrayList<Integer> subset = new ArrayList<Integer>();
int index = 0;
while (i > 0) {
if ((i & 1) > 0) {
subset.add(set.get(index)); //Add elements to a new ArrayList
}
i >>= 1;
index++;
}
allsubsets.add(subset);
}
You'll notice that the outside for-loop is trying to count i upwards from zero, and the inner while loop counts it back to zero every iteration, so the outer loop runs forever.

Here is a Java 8 solution for this question:
public Set<Set<Integer>> getSubsets(Set<Integer> set) {
if (set.isEmpty()) {
return Collections.singleton(Collections.emptySet());
}
Set<Set<Integer>> subSets = set.stream().map(item -> {
Set<Integer> clone = new HashSet<>(set);
clone.remove(item);
return clone;
}).map(group -> getSubsets(group))
.reduce(new HashSet<>(), (x, y) -> {
x.addAll(y);
return x;
});
subSets.add(set);
return subSets;
}

Program runs forever. Below statement execute continuesly and getting outOfMemory. Variable i value is never bigger than max value, check it.
`subset.add(set.get(index));`

In a nutshell, your inner while-loop is changing the outer for-loop's loop variable (i). This is disrupting the outer loop iteration. At the end of the inner loop the value of i is going to be zero ... which means that the outer loop will never terminate.
Given what you are doing, the fix is to use a different variable (say j) for the inner loop, and initialize it from i.
This illustrates why it is a bad idea to change a for-loop variable inside the loop.

how about a recursive solution?
vector<vector<int> > getSubsets(vector<int> a){
//base case
//if there is just one item then its subsets are that item and empty item
//for example all subsets of {1} are {1}, {}
if(a.size() == 1){
vector<vector<int> > temp;
temp.push_back(a);
vector<int> b;
temp.push_back(b);
return temp;
}
else
{
//here is what i am doing
// getSubsets({1, 2, 3})
//without = getSubsets({1, 2})
//without = {1}, {2}, {}, {1, 2}
//with = {1, 3}, {2, 3}, {3}, {1, 2, 3}
//total = {{1}, {2}, {}, {1, 2}, {1, 3}, {2, 3}, {3}, {1, 2, 3}}
//return total
int last = a[a.size() - 1];
a.pop_back();
vector<vector<int> > without = getSubsets(a);
vector<vector<int> > with = without;
for(int i=0;i<without.size();i++){
with[i].push_back(last);
}
vector<vector<int> > total;
for(int j=0;j<without.size();j++){
total.push_back(without[j]);
}
for(int k=0;k<with.size();k++){
total.push_back(with[k]);
}
return total;
}
}

Related

In Java code i the method i created only put the first duplicate instance to a new array

I want to remove the duplicates by putting them in a new array but somehow I only get a first instance and a bunch of zeros.
Here is my code:
public class JavaApplication7 {
public static void main(String[] args) {
int[] arr = new int[] {1,1,2,2,2,2,3,4,5,6,7,8};
int[] res = removeD(arr);
for (int i = 0; i < res.length; i++) {
System.out.print(res[i] + " ");
}
}
public static int[] removeD(int[] ar) {
int[] tempa = new int[ar.length];
for (int i = 0; i < ar.length; i++) {
if (ar[i] == ar[i+1]) {
tempa[i] = ar[i];
return tempa;
}
}
return null;
}
}
expected: 1,2
result: 1,0,0,0,0,0,0....
why dont you make use of HashSet?
final int[] arr = new int[] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8 };
final Set<Integer> set = new HashSet<>();
for (final int i : arr) {
// makes use of Integer's hashCode() and equals()
set.add(Integer.valueOf(i));
}
// primitive int array without zeros
final int[] newIntArray = new int[set.size()];
int counter = 0;
final Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
newIntArray[counter] = iterator.next().intValue();
counter++;
}
for (final int i : newIntArray) {
System.out.println(i);
}
Edit
if you want your array to be ordered
final int[] arr = new int[] { 9, 9, 8, 8, 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8 };
Set<Integer> set = new HashSet<>();
for (final int i : arr) {
// makes use of Integer's hashCode() and equals()
set.add(Integer.valueOf(i));
}
// priomitive int array without zeros
final int[] newIntArray = new int[set.size()];
int counter = 0;
// SetUtils.orderedSet(set) requires apache commons collections
set = SetUtils.orderedSet(set);
final Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
newIntArray[counter] = iterator.next().intValue();
counter++;
}
for (final int i : newIntArray) {
System.out.println(i);
}
A couple of points to help you:
1) With this: for(int i =0; i<ar.length; i++){ - you will get an IndexOutOfBoundsException because you are checking [i+1]. Hint: it is only the last element that will cause this...
2) Because you're initialising the second array with the length of the original array, every non-duplicate will be a 0 in it, as each element is initialised with a 0 by default. So perhaps you need to find how many duplicates there are first, before setting the size.
3) As mentioned in the comments, you are returning the array once the first duplicate is found, so remove that and just return the array at the end of the method.
4) You will also get multiple 2s because when you check i with i+1, it will find 3 2s and update tempa with each of them, so you'll need to consider how to not to include duplicates you've already found - based on your expected result.
These points should help you get the result you desire - if I (or someone else) just handed you the answer, you wouldn't learn as much as if you researched it yourself.
Here:
int[] tempa = new int[ar.length];
That creates a new array with the same size as the incoming one. All slots in that array are initialized with 0s!
When you then put some non-0 values into the first slots, sure, those stick, but so do the 0s in all the later slots that you don't "touch".
Thus: you either have to use a data structure where you can dynamically add new elements (like List/ArrayList), or you have to first iterate the input array to determine the exact count of objects you need, to then create an appropriately sized array, to then fill that array.
Return statement
As both commenters said, you return from the method as soon as you find your first duplicate. To resolve that issue, move the return to the end of the method.
Index problems
You will then run into another issue, an ArrayIndexOutOfBoundsException because when you are checking your last item (i = ar.length - 1) which in your example would be 11 you are then comparing if ar[11] == ar[12] but ar has size 12 so index 12 is out of the bounds of the array. You could solve that by changing your exit condition of the for loop to i < ar.length - 1.
Zeros
The zeros in your current output come from the initialization. You initialize your tempa with int[ar.length] this means in the memory it will reserve space for 12 ints which are initialized with zero. You will have the same problem after resolving both issues above. Your output would look like this: 1 0 2 2 2 0 0 0 0 0 0 0. This is because you use the same index for tempa and ar. You could solve that problem in different ways. Using a List, Filtering the array afterwards, etc. It depends what you want to do exactly.
The code below has the two first issues solved:
public class JavaApplication7 {
public static void main(String[] args) {
int[] arr = new int[] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8 };
int[] res = removeD(arr);
for (int i = 0; i < res.length; i++) {
System.out.print(res[i] + " ");
}
}
public static int[] removeD(int[] ar) {
int[] tempa = new int[ar.length];
for (int i = 0; i < ar.length - 1; i++) {
if (ar[i] == ar[i + 1]) {
tempa[i] = ar[i];
}
}
return tempa;
}
}
There were a some error mentioned already:
return exits the method.
with arr[i+1] the for condition should bei+1 < arr.length`.
the resulting array may be smaller.
So:
public static int[] removeD(int[] ar) {
// Arrays.sort(ar);
int uniqueCount = 0;
for (int i = 0; i < ar.length; ++i) {
if (i == 0 || ar[i] != ar[i - 1]) {
++uniqueCount;
}
}
int[] uniques = new int[uniqueCount];
int uniqueI = 0;
for (int i = 0; i < ar.length; ++i) {
if (i == 0 || ar[i] != ar[i - 1]) {
uniques[uniqueI] = arr[i];
++uniqueI;
}
}
return uniques;
}

Largest product in a series (java)

I'm trying to find the 3 adjacent numbers that produce the maximum product given a 9 digit number. For example for the number 198348756 my solution should return [8,7,5] since the product of this is 280 and is the maximum product possible.My code finds the max product but cannot return the array of digits that create the max product. Instead it returns the last array it checks in the for loop. I cannot understand why the array of digits that create the max product isn't stored in the variable result?
public class Solution {
ArrayList<Integer> digits = new ArrayList<>();
/// digits to int array
void tocharArray(String num) {
char[] charArray = num.toCharArray();
for (Character c : charArray) {
digits.add(Character.getNumericValue(c));
}
//System.out.println(digits);
//System.out.println(digits.size());
}
//gets product of array ex [1,2,3] ->6
int arrayproduct(ArrayList<Integer> array) {
int product = 1;
for(int i=0;i < array.size(); i++) {
product = product * array.get(i);
}
return product;
}
ArrayList<Integer> func() {
ArrayList<Integer> three = new ArrayList<>();
ArrayList<Integer> result = new ArrayList<>();
// array of the first 3 digits of the number
for(int index = 0; index < 3;index++) {
three.add(digits.get(index));
}
//initially the max product is the first 3 digits
int maxproduct = arrayproduct(three);
System.out.println(three); //from test [1,9,8]
System.out.println(maxproduct);// from test 72
ArrayList<Integer> copy = three;
for(int j = 3 ; j < digits.size();j++) {
copy.remove(0);
copy.add(digits.get(j));
int next = arrayproduct(copy);
System.out.println(copy);
if(next > maxproduct) {
maxproduct = next;
result = copy;
}
}
System.out.println(maxproduct); // returns 280 which is correct
System.out.println(result); // returns [7,5,6]
return result;
}
public static void main(String[] args) {
String test1 = "198348756";
Solution sol = new Solution();
sol.tocharArray(test1); \\[1,9,8,3,4,8,7,5,6]
sol.arrayproduct(sol.digits); \\returns [7,5,6] which is incorrect
sol.func();
}
}
The problem is on this line:
ArrayList<Integer> copy = three;
Your code assumes that copy is, well, a copy, but in reality it is an alias to the same three list.
You can fix it by actually copying the list:
ArrayList<Integer> copy = new ArrayList<>(three);
Same goes for result = copy - it needs to be result = new ArrayList<>(copy)
Note: You can further simplify this code by changing arrayproduct to take the initial index and length. This way you would be able to avoid creating new lists as you go. Once the proper location is found, you would be able to make a copy of three-element subrange by calling subList.
A easier approach
ArrayList<Integer> getMaxConsecutive(ArrayList<Integer> arr)
{
ArrayList<Integer> result = new ArrayList<Integer>();
int start=-1;
int max=INT_MIN;
for(int i=0;i<(arr.size()-3);i++)
{
int sum = arr.get(i)+arr.get(i+1)+arr.get(i+2);
if(sum>max){
max=sum;
start = i;
}
}
result.add(arr.get(start));
result.add(arr.get(start+1));
result.add(arr.get(start+2));
return result;
}
From the source code:
for (int j = 3; j < digits.size(); j++) {
copy.remove(0);
copy.add(digits.get(j));
int next = arrayproduct(copy);
System.out.println("-->" + next);
System.out.println("-->" + copy);
if (next > maxproduct) {
maxproduct = next;
result = copy;
System.out.println("result-->" + result);
}
}
The variable copy and result are object references like a pointer of C.
So, you need to copy(clone) all contents of copy's contents to the result object explicitly whenever the maxproduct value changes. There are several ways to accomplish about this method.
Using a clone method is one simple way to do;
result = copy;
to
result = (ArrayList<Integer>)copy.clone();
So, the func method is as follows:
#SuppressWarnings("unchecked")
ArrayList<Integer> func() {
ArrayList<Integer> three = new ArrayList<>();
ArrayList<Integer> result = new ArrayList<>();
// array of the first 3 digits of the number
for (int index = 0; index < 3; index++) {
three.add(digits.get(index));
}
// initially the max product is the first 3 digits
int maxproduct = arrayproduct(three);
System.out.println(three); // from test [1,9,8]
System.out.println(maxproduct);// from test 72
ArrayList<Integer> copy = three;
for (int j = 3; j < digits.size(); j++) {
copy.remove(0);
copy.add(digits.get(j));
int next = arrayproduct(copy);
System.out.println(copy);
if (next > maxproduct) {
maxproduct = next;
result = (ArrayList<Integer>)copy.clone();
}
}
System.out.println(maxproduct); // returns 280 which is correct
System.out.println(result); // returns [7,5,6]
return result;
}
Then the output message might be what you expected.
[1, 9, 8]
72
[9, 8, 3]
[8, 3, 4]
[3, 4, 8]
[4, 8, 7]
[8, 7, 5]
[7, 5, 6]
280
[8, 7, 5]
Have a good coding...

Removing specific value from array (java)

i have integer a = 4 and array b 7,8,9,4,3,4,4,2,1
i have to write a method that removes int ALL a from array b
desired result 7,8,9,3,2,1
This is what I have so far,
public static int[] removeTwo (int x, int[] array3)
{
int counter = 0;
boolean[] barray = new boolean [array3.length];
for (int k=0; k<array3.length; k++)
{
barray[k] = (x == array3[k]);
counter++;
}
int[] array4 = new int [array3.length - counter];
int num = 0;
for (int j=0; j<array3.length; j++)
{
if(barray[j] == false)
{
array4[num] = array3[j];
num++;
}
}
return array4;
I get this error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Utility.removeTwo(Utility.java:50)
at Utility.main(Utility.java:18)
Java Result: 1
Any help would be much appreciated!
The error stems from this for loop:
for (int k=0; k<array3.length; k++)
{
barray[k] = (x == array3[k]);
counter++;
}
when you create int[] array4 = new int [array3.length - counter]; you are creating an array with size 0. You should only increment the counter if the item is the desired item to remove:
for (int k=0; k<array3.length; k++)
{
boolean b = (x == array3[k]);
barray[k] = b;
if(b) {
counter++;
}
}
To answer your question in the comment, the method should be called and can be checked like this:
public static void main(String[] args) {
int[] array3 = {0,1,3,2,3,0,3,1};
int x = 3;
int[] result = removeTwo(x, array3);
for (int n : result) {
System.out.print(""+ n + " ");
}
}
On this line:
int[] array4 = new int [array3.length - counter];
You create an array with size 0, as counter is equal to array3.length at this point.
This means that you cannot access any index in that array.
You are creating
int[] array4 = new int [array3.length - counter];// 0 length array.
you can't have 0th index there. At least length should 1 to have 0th index.
BTW my suggestion, it is better to use List. Then you can do this easy.
Really an Array is the wrong tool for the job, since quite apart from anything else you will end up with stray values at the end that you cannot remove. Just use an ArrayList and that provides a removeAll() method to do what you need. If you really need arrays you can even do:
List<Integer> list = new ArrayList(Arrays.asList(array))
list.removeAll(4);
array = list.toArray();
(Exact method names/parameters may need tweaking as that is all from memory).
the simplest way is to work with a second array where you put in the correct values
something likte that
public static int[] removeTwo (int x, int[] array3)
{
int counter = 0;
int[] array4 = new int[array3.lenght];
for (int i = 0; i < array3.lenght; i ++) {
if(array3[i] == x){
array4[counter] = array3[i];
}
}
return array4;
}
anoterh way is to remove the x calue from the array3 and shift the values behind forward
The best way to remove element from array is to use List with Iterator. Try,
Integer[] array = {7, 8, 9, 4, 3, 4, 4, 2, 1};
List<Integer> list = new ArrayList(Arrays.asList(array));
for(Iterator<Integer> it=list.iterator();it.hasNext();){
if(it.next()==4){
it.remove();
}
}

Removing duplicates from array without using Util classes

Please read the question before marking it as duplicate
I have written following code to remove duplicates from array without using Util classes but now I am stuck
public class RemoveDups{
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 3, 1, 4, 52, 1, 45, };
int temp;
for (int i : a) {
for (int j = 0; j < a.length - 1; j++) {
if (a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
a = removeDups(a);
for (int i : a) {
System.out.println(i);
}
}
private static int[] removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
for (int i : a) {
if (!isExist(result, i)) {
result[j++] = i;
}
}
return result;
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
and now the output is
1
2
3
4
5
6
45
52
0
0
0
0
0
0
0
0
0
0
Here my problem is
My code is not working in case of 0s
I am not able to understand how sorting an array can reduce time of execution
Is there any way to remove elements from array without using Util classes I know one way to remove convert array into list and then remove but for that also we need Util classes is there any way to implement by myself.
Since the numbers you deal with are limited to a small range you can remove duplicates by a simple "counting sort": mark the numbers you have found in a set-like data structure and then go over the data structure. An array of boolean works just fine, for less memory usage you could create a basic bitset or hash table. If n is the number of elements in the array and m is the size of the range, this algorithm will have O(n+m) complexity.
private static int[] removeDups(int[] a, int maxA) {
boolean[] present = new boolean[maxA+1];
int countUnique = 0;
for (int i : a) {
if (!present[i]) {
countUnique++;
present[i] = true;
}
}
int[] result = new int[countUnique];
int j = 0;
for (int i=0; i<present.length; i++) {
if (present[i]) result[j++] = i;
}
return result;
}
I am not able to understand how sorting an array can reduce time of execution
In a sorted array you can detect duplicates in a single scan, taking O(n) time. Since sorting is faster than checking each pair - O(n log n) compared to O(n²) time complexity - it would be faster to sort the array instead of using the naive algorithm.
As you are making the result array of the same length as array a
so even if you put only unique items in it, rest of the blank items will have the duplicate values in them which is 0 for int array.
Sorting will not help you much, as you code is searching the whole array again and again for the duplicates. You need to change your logic for it.
You can put some negative value like -1 for all the array items first in result array and then you can easily create a new result array say finalResult array from it by removing all the negative values from it, It will also help you to remove all the zeroes.
In java , arrays are of fixed length. Once created, their size can't be changed.
So you created an array of size18.
Then after you applied your logic , some elements got deleted. But array size won't change. So even though there are only 8 elements after the duplicate removal, the rest 10 elements will be auto-filled with 0 to keep the size at 18.
Solution ?
Store the new list in another array whose size is 8 ( or whatever, calculate how big the new array should be)
Keep a new variable to point to the end of the last valid element, in this case the index of 52. Mind you the array will still have the 0 values, you just won't use them.
I am not able to understand how sorting an array can reduce time of execution
What ? You sort an array if you need it to be sorted. Nothing else. Some algorithm may require the array to be sorted or may work better if the array is sorted. Depends on where you are using the array. In your case, the sorting will not help.
As for your final question , you can definitely implement your own duplicate removal by searching if an element exists more than once and then deleting all the duplicates.
My code is not working in case of 0
There were no zeroes to begin with in your array. But because its an int[], after the duplicates are removed the remaining of the indexes are filled with 0. That's why you can see a lot of zeroes in your array. To get rid of those 0s, you need to create another array with a lesser size(size should be equal to the no. of unique numbers you've in your array, excluding 0).
If you can sort your array(I see that its already sorted), then you could either bring all the zeroes to the front or push them to the last. Based on that, you can iterate the array and get the index from where the actual values start in the array. And, then you could use Arrays.copyOfRange(array, from, to) to create a copy of the array only with the required elements.
try this
package naveed.workingfiles;
public class RemoveDups {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 3, 1, 4, 52, 1, 45, };
removeDups(a);
}
private static void removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
int count = 0;
for (int i : a) {
if (!isExist(result, i)) {
result[j++] = i;
count++;
}
}
System.out.println(count + "_____________");
for (int i=0;i<count;i++) {
System.out.println(result[i]);
}
// return result;
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
public class RemoveDups {
public static void main(String[] args) {
int[] a = { 1, 2, 0, 3, 1,0, 3, 6, 2};
removeDups(a);
}
private static void removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
int count = 0;
boolean zeroExist = false;
for (int i : a) {
if(i==0 && !zeroExist){
result[j++] = i;
zeroExist = true;
count++;
}
if (!isExist(result, i)) {
result[j++] = i;
count++;
}
}
System.out.println(count + "_____________");
for (int i=0;i<count;i++) {
System.out.println(result[i]);
}
// return result;
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
// It works even Array contains 'Zero'
class Lab2 {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 3, 1, 4, 52, 1, 45 };
removeDups(a);
}
private static void removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
int count = 0;
for (int i : a) {
if (!isExist(result, i)) {
result[j++] = i;
count++;
}
}
System.out.println(count + "_____________");
for (int i = 0; i < count; i++) {
System.out.println(result[i]);
}
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}

Java, find intersection of two arrays

I have already read a few other stack overflow threads on this:
to find the intersection of two multisets in java
How do I get the intersection between two arrays as a new array?
public static int[] intersection (int [] x, int numELementsInX, int [] y, int numElementsInY) {
I am trying to examine two arrays as well as their number of elements (numElementsInX and numElementsInY), and return a new array which contains the common values of array x and y. Their intersection.
Example,if x is{1,3,5,7,9}and y is{9,3,9,4} then
intersection(x, 5, y, 4} should return {3, 9} or {9, 3}
I've read I need to use the LCS algorithm. Can anyone give me an example as to how to do this? Both the array and values in array are initialized and generated in another method, then passed into intersection.
Any help/clarification is appreciated.
EDIT CODE
for (int i=0; i<numElementsInX; i++){
for (int j=0; j<numElementsInY; j++){
if (x[j]==x[i]) { //how to push to new array?;
}
else{
}
}
}
The simplest solution would be to use sets, as long as you don't care that the elements in the result will have a different order, and that duplicates will be removed. The input arrays array1 and array2 are the Integer[] subarrays of the given int[] arrays corresponding to the number of elements that you intend to process:
Set<Integer> s1 = new HashSet<Integer>(Arrays.asList(array1));
Set<Integer> s2 = new HashSet<Integer>(Arrays.asList(array2));
s1.retainAll(s2);
Integer[] result = s1.toArray(new Integer[s1.size()]);
The above will return an Integer[], if needed it's simple to copy and convert its contents into an int[].
If you are fine with java-8, then the simplest solution I can think of is using streams and filter. An implementation is as follows:
public static int[] intersection(int[] a, int[] b) {
return Arrays.stream(a)
.distinct()
.filter(x -> Arrays.stream(b).anyMatch(y -> y == x))
.toArray();
}
General test
The answers provide several solutions, so I decided to figure out which one is the most effective.
Solutions
HashSet based by Óscar López
Stream based by Bilesh Ganguly
Foreach based by Ruchira Gayan Ranaweera
HashMap based by ikarayel
What we have
Two String arrays that contain 50% of the common elements.
Every element in each array is unique, so there are no duplicates
Testing code
public static void startTest(String name, Runnable test){
long start = System.nanoTime();
test.run();
long end = System.nanoTime();
System.out.println(name + ": " + (end - start) / 1000000. + " ms");
}
With use:
startTest("HashMap", () -> intersectHashMap(arr1, arr2));
startTest("HashSet", () -> intersectHashSet(arr1, arr2));
startTest("Foreach", () -> intersectForeach(arr1, arr2));
startTest("Stream ", () -> intersectStream(arr1, arr2));
Solutions code:
HashSet
public static String[] intersectHashSet(String[] arr1, String[] arr2){
HashSet<String> set = new HashSet<>(Arrays.asList(arr1));
set.retainAll(Arrays.asList(arr2));
return set.toArray(new String[0]);
}
Stream
public static String[] intersectStream(String[] arr1, String[] arr2){
return Arrays.stream(arr1)
.distinct()
.filter(x -> Arrays.asList(arr2).contains(x))
.toArray(String[]::new);
}
Foreach
public static String[] intersectForeach(String[] arr1, String[] arr2){
ArrayList<String> result = new ArrayList<>();
for(int i = 0; i < arr1.length; i++){
for(int r = 0; r < arr2.length; r++){
if(arr1[i].equals(arr2[r]))
result.add(arr1[i]);
}
}
return result.toArray(new String[0]);
}
HashMap
public static String[] intersectHashMap(String[] arr1, String[] arr2){
HashMap<String, Integer> map = new HashMap<>();
for (int i = 0; i < arr1.length; i++)
map.put(arr1[i], 1);
ArrayList<String> result = new ArrayList<>();
for(int i = 0; i < arr2.length; i++)
if(map.containsKey(arr2[i]))
result.add(arr2[i]);
return result.toArray(new String[0]);
}
Testing process
Let's see what happens if we give the methods an array of 20 elements:
HashMap: 0.105 ms
HashSet: 0.2185 ms
Foreach: 0.041 ms
Stream : 7.3629 ms
As we can see, the Foreach method does the best job. But the Stream method is almost 180 times slower.
Let's continue the test with 500 elements:
HashMap: 0.7147 ms
HashSet: 4.882 ms
Foreach: 7.8314 ms
Stream : 10.6681 ms
In this case, the results have changed dramatically. Now the most efficient is the HashMap method.
Next test with 10 000 elements:
HashMap: 4.875 ms
HashSet: 316.2864 ms
Foreach: 505.6547 ms
Stream : 292.6572 ms
The fastest is still the HashMap method. And the Foreach method has become quite slow.
Results
If there are < 50 elements, then it is best to use the Foreach method. He strongly breaks away in speed in this category.
In this case, the top of the best will look like this:
Foreach
HashMap
HashSet
Stream - Better not to use in this case
But if you need to process big data, then the best option would be use the HashMap based method.
So the top of the best look like this:
HashMap
HashSet
Stream
Foreach
With duplicate elements in array finding intersection.
int [] arr1 = {1,2,2,2,2,2,2,3,6,6,6,6,6,6,};
int [] arr2 = {7,5,3,6,6,2,2,3,6,6,6,6,6,6,6,6,};
Arrays.sort(arr1);
Arrays.sort(arr2);
ArrayList result = new ArrayList<>();
int i =0 ;
int j =0;
while(i< arr1.length && j<arr2.length){
if (arr1[i]>arr2[j]){
j++;
}else if (arr1[i]<arr2[j]){
i++;
}else {
result.add(arr1[i]);
i++;
j++;
}
}
System.out.println(result);
If you don't want to use other data structures such as a Set, then the basic idea is that you want to iterate through the elements of one of the arrays and for each value see if it appears in the other. How do you see whether it appears in the other array? Walk through the elements in the other array and for each one, see if its value is equal to the value you are looking for. I suspect that you will be best served by trying to work through this problem on your own beyond this point if your goal in taking the class is to learn to write Java well, but it you get stuck you might consider updating your question with the code that you have written so you can get more detailed feedback and pointers in the right direction.
Try this:
public static void main(String[] args) {
int[] arr1 = new int[]{1, 2, 3, 4, 5};
int[] arr2 = new int[]{3, 2, 5, 9, 11};
getIntersection(arr1, arr2);
}
public static Object[] getIntersection(int[] arr1, int[] arr2) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr2.length; j++) {
if (arr1[i] == arr2[j]) {
list.add(arr1[i]);
}
}
}
return list.toArray();
}
You can find the intersection of two arrays with:
T[] result = Arrays.stream(a1)
.filter(new HashSet<>(Arrays.asList(a2))::contains)
.toArray(T[]::new);
where T should be substitutable by a reference type e.g. String, Integer, etc.
although the above may seem like it's creating a new set for each element, it's not the case at all. instead only one set instance is created.
The above code is equivalent to:
List<T> list = new ArrayList<>();
HashSet<T> container = new HashSet<>(Arrays.asList(a2));
for (T s : a1) {
if (container.contains(s)) list.add(s);
}
T[] result = list.toArray(new T[0]);
finding intersection includes duplicate using the hash map.
Output: 1 2 2 15 9 7 12
public static void main(String[] args) {
int[] arr1 = {1, 2, 2, 1, 5, 9, 15, 9, 7, 7, 12};
int[] arr2 = {1, 2, 2, 3, 4, 15, 9, 7, 12, 14};
printIntersect(arr1, arr2);
}
private static void printIntersect(int[] arr1, int[] arr2) {
Map<Integer, Integer> map = new HashMap<>();
//put first array to map
for (int i = 0; i < arr1.length; i++) {
if (!map.containsKey(arr1[i])) {
map.put(arr1[i], 1);
} else {
map.put(arr1[i], map.get(arr1[i]) + 1);
}
}
//check all value in array two
for (int i = 0; i < arr2.length; i++) {
//if exist and value>1 then decrement value
//if value is 1 remove from map
if (map.containsKey(arr2[i])) {
System.out.print(arr2[i] + " ");
if (map.get(arr2[i]) > 1) {
map.put(arr2[i], map.get(arr2[i]) - 1);
} else {
map.remove(arr2[i]);
}
}
}
}
if the arrays are sorted
int a1[]=new int[] {1,2,3,5,7,8};
int a2[]=new int [] {1,5,6,7,8,9};
// get the length of both the array
int n1=a1.length;
int n2=a2.length;
//create a new array to store the intersection
int a3[]=new int[n1];
//run the loop and find the intersection
int i=0,j=0,k=0;
while(i<n1&& j<n2) {
if(a1[i]<a2[j]) {
// a1 element at i are smaller than a2 element at j so increment i
i++;
}else if(a1[i]>a2[j]) {
// a2 element at i are smaller than a2 element at j so increment j
j++;
}else {
// intersection element store the value and increment i, j, k to find the next element
a3[k]=a1[i];
i++;
j++;
k++;
}
}
for(int l=0;l<a3.length;l++) {
System.out.println(a3[l]);
}
How to Find the Intersection of 3 unsorted arrays in Java:-
I have used the Core Java approach using for loops & using Arrays.copyOf to achieve this.
public class Intersection {
public void intersection3Arrays(int ar1[], int ar2[], int ar3[]) {
Arrays. sort(ar1);
Arrays. sort(ar2);
Arrays. sort(ar3);
int ar1Len = ar1.length;
int ar2Len = ar2.length;
int ar3Len = ar3.length;
int larArray = ar3Len > (ar1Len > ar2Len ? ar1Len : ar2Len) ? ar3Len : ((ar1Len > ar2Len) ? ar1Len : ar2Len);
System.out.println("The largest array is " +larArray);
int[] inputArray1 = Arrays.copyOf(ar1, larArray);
int[] inputArray2 = Arrays.copyOf(ar2, larArray);
int[] inputArray3 = Arrays.copyOf(ar3, larArray);
Integer[] inputArray11 = new Integer[inputArray1.length];
Integer[] inputArray22 = new Integer[inputArray2.length];
Integer[] inputArray33 = new Integer[inputArray3.length];
for (int i = 0; i < inputArray11.length; i++) {
if (inputArray11[i] == null){
inputArray1[i] = 0;
}
}
for (int i = 0; i < inputArray22.length; i++) {
if (inputArray22[i] == null){
inputArray1[i] = 0;
}
}
for (int i = 0; i < inputArray33.length; i++) {
if (inputArray33[i] == null){
inputArray1[i] = 0;
}
}
for (int i = 0; i < inputArray11.length; i++)
for (int j = 0; j < inputArray22.length; j++)
for (int k = 0; k < inputArray33.length; j++)
if (inputArray11[i] == inputArray22[j] && inputArray11[i] == inputArray33[k]) {
System.out.print(inputArray11[i]+" ");
}
}
public static void main(String[] args) {
Intersection3Arrays arrays = new Intersection3Arrays();
int ar1[] = { 1, 2, 5, 10, 20, 40, 80 };
int ar2[] = { 80, 100, 6, 2, 7, 20 };
int ar3[] = {3, 4, 15, 20, 30, 70, 80, 120};
arrays.intersection3Arrays(ar1, ar2, ar3);
}
}
If you ever wanted to implement this in python, this is one way that you can find intersection.
#find intersection
def find_intersec(list_a, list_b):
return set(list_a).intersection(list_b)
#since lists are kind of like arrays in python we use two lists
list_a = [ 4, 9, 1, 17, 11, 26, 28, 10,28, 26, 66, 91]
list_b = [9, 9, 74, 21, 45, 11, 63,10]
print(find_intersec(list_a, list_b))
I hope this example will simple one.pass two arrays and you will definitely get INTERSECTION of array without duplicate items.
private static int[] findInterserctorOfTwoArray(int[] array1, int[] array2) {
Map<Integer,Integer> map=new HashMap<>();
for (int element : array1) {
for (int element2 : array2) {
if(element==element2) {
map.put(element, element);
}
}
}
int[] newArray=new int[map.size()];
int con=0;
for(Map.Entry<Integer, Integer> lst:map.entrySet()) {
newArray[con]=lst.getValue();
con++;
}
return newArray;
}
optimised for sorted arrays using only one loop.
int a1[]=new int[] {1,2,3,5,7,8};
int a2[]=new int [] {1,5,6,7,8,9};
// sort both the array
Arrays.sort(a1);
Arrays.sort(a2);
// get the length of both the array
int n1=a1.length;
int n2=a2.length;
//create a new array to store the intersection
int a3[]=new int[n1];
//run the loop and find the intersection
int i=0,j=0,k=0;
while(i<n1&& j<n2) {
if(a1[i]<a2[j]) {
// a1 element at i are smaller than a2 element at j so increment i
i++;
}else if(a1[i]>a2[j]) {
// a2 element at i are smaller than a2 element at j so increment j
j++;
}else {
// intersection element store the value and increment i, j, k to find the next element
a3[k]=a1[i];
i++;
j++;
k++;
}
}
for(int l=0;l<a3.length;l++) {
System.out.println(a3[l]);
}
Primitive Iterator: 6 Times Faster than HashSet
Tested on sorted arrays of 10,000,000 random elements, values between 0 and 200,000,000. Tested on 10 processor i9 with 4GB heap space. Sort time for two arrays was 1.9 seconds.
results:
primitive() - 1.1 seconds
public static int[] primitive(int[] a1, int[] a2) {
List<Integer> list = new LinkedList<>();
OfInt it1 = Arrays.stream(a1).iterator();
OfInt it2 = Arrays.stream(a2).iterator();
int i1 = it1.next();
int i2 = it2.next();
do {
if (i1==i2) {
list.add(i1);
i1 = it1.next();
}
if (i1 < i2) i1 = it1.next();
if (i2 < i1) i2 = it2.next();
} while(it1.hasNext() && it2.hasNext());
if (i1==i2) list.add(i1);
return list.stream().mapToInt(Integer::intValue).toArray();
}
boxed() - 6.8 seconds
public static int[] boxed(int[] a1, int[] a2) {
return Arrays.stream(a1)
.filter(new HashSet<>(Arrays.stream(a2).boxed()
.collect(Collectors.toList()))::contains)
.toArray();
}

Categories