I have this array in Java:
private int[] all = new int [] {0,1,2,3,4,5};
I want to set a new var that equal to all-{2,3,5} (equals {0,1,4})
Is there any build-in function that performs subtraction between two arrays?
You can code up set subtraction using Java 8 streams.
The idea is to construct a hash set of integers that you would like to exclude, and then run through the original array, check each element against the exclusion set in O(1), and keep only elements that should not be excluded.
int[] all=new int [] {0,1,2,3,4,5};
int[] ex=new int [] {2,3,5};
Set<Integer> exSet = IntStream.of(ex).boxed().collect(Collectors.toCollection(HashSet::new));
int[] res = IntStream.of(all).filter(val -> !exSet.contains(val)).toArray();
Demo.
I understood what you want to say and figured out a way to do that , what exactly you want.
If you use ArrayList then you could use removerAll() to remove or subtract.
Lets see this on the working code
import java.util.ArrayList;
public class removeAllInArrayList {
public static void main(String[] args) {
ArrayList <Integer> numbers = new ArrayList<Integer>();
numbers.add(0);
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);
System.out.print("The number array contains:- \t");
display (numbers);
ArrayList <Integer> numbers2 = new ArrayList<Integer>();
numbers2.add(0);
numbers2.add(2);
numbers2.add(4);
numbers2.add(6);
System.out.print("The number2 array contains:- \t ");
display(numbers2);
System.out.println("Subtract number2 from number.");
numbers.removeAll(numbers2);
System.out.print("Now, number array contains:- \t");
display (numbers);
}
public static void display (ArrayList array){
for (int i =0 ; i < array.size() ; i++){
System.out.print(array.get(i) + " ");
}
System.out.println ();
}
}
The result of the following code is
The number array contains:- 0 1 2 3 4 5
The number2 array contains:- 0 2 4 6
Subtract number2 from number.
Now, number array contains:- 1 3 5
Hope this works , and helps to solve out the code.
I don't think there is such a build-in method. You can try to find some library which can do that, or write your own method:
public static int[] removeEqual(int[] a_arr, int[] b_arr) {
List<Integer> list = new ArrayList<>();
for (int a : a_arr) { list.add(a); }
Iterator<Integer> iter = list.iterator();
while(iter.hasNext()) {
int a = iter.next();
for (int b : b_arr) {
if (a == b) {iter.remove();}
}
}
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {result[i] = list.get(i);}
return result;
}
Test
public static void main(String[] args) {
System.out.println("expected: [0, 1, 4], actual: " +
Arrays.toString(removeEqual(new int[] {0,1,2,3,4,5}, new int[] {2, 3, 5})));
}
Output: expected: [0, 1, 4], actual: [0, 1, 4]
You can do what you want with lists:
List<Integer> all = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5));
List<Integer> toRemove = Arrays.asList(2, 3, 5);
all.removeAll(toRemove);
System.out.println(all); // [0, 1, 4]
In order to be able to remove elements from the all list, you should create it with the new ArrayList<>(anotherList) constructor, since the lists returned by Arrays.asList cannot be structurally modified.
I tested Streams vs Collections:
public static void main(String... args)
{
Random rand = new Random();
int[] all = new int[100000];
int[] ex = new int[50000];
fillArrays(rand, all, ex);
long start = System.currentTimeMillis();
testWithStreams(all, ex);
System.out.println(String.format("Streams: %d", System.currentTimeMillis() - start));
fillArrays(rand, all, ex);// Avoid any external optimization
start = System.currentTimeMillis();
testWithCollections(all, ex);
System.out.println(String.format("Collections: %d", System.currentTimeMillis() - start));
fillArrays(rand, all, ex);// Avoid any external optimization
start = System.currentTimeMillis();
testWithCollectionsToArray(all, ex);
System.out.println(String.format("Collections -> Array: %d", System.currentTimeMillis() - start));
fillArrays(rand, all, ex);// Avoid any external optimization
start = System.currentTimeMillis();
testWithStreamsAndSet(all, ex);
System.out.println(String.format("Streams + HashSet: %d", System.currentTimeMillis() - start));
}
private static void fillArrays(Random rand, int[] all, int[] ex)
{
for (int i = 0; i < all.length; i++)
{
all[i] = rand.nextInt();
}
for (int i = 0; i < ex.length; i++)
{
ex[i] = all[rand.nextInt(all.length)];
}
// System.out.println(String.format("all values: %d, %d, %d", all[0], all[1], all[2]));
// System.out.println(String.format("ex values: %d, %d, %d", ex[0], ex[1], ex[2]));
}
private static int[] testWithStreams(int[] all, int[] ex)
{
return Arrays.stream(all).filter(
(elementOfAll) -> Arrays.stream(ex).noneMatch(
(elementOfEx) -> elementOfAll == elementOfEx
)
).toArray();
}
private static List<Integer> testWithCollections(int[] all, int[] ex)
{
List<Integer> listOfAll = Arrays.stream(all).boxed().collect(Collectors.toList());
listOfAll.removeAll(Arrays.stream(ex).boxed().collect(Collectors.toList()));
return listOfAll;
}
private static int[] testWithCollectionsToArray(int[] all, int[] ex)
{
return testWithCollections(all, ex).stream().mapToInt((v) -> v).toArray();
}
private static int[] testWithStreamsAndSet(int[] all, int[] ex)
{
HashSet<Integer> exSet = Arrays.stream(ex).boxed().collect(Collectors.toCollection(HashSet::new));
return Arrays.stream(all).filter((element) -> !exSet.contains(element)).toArray();
}
The Output:
Streams: 13823
Collections: 2905
Collections -> Array: 2931
Streams + HashSet: 29
EDIT:
Added the example of dasblinkenlight
Related
I am writing code for Mo's algorithm with update in JAVA , so in this we have to order in ascending order an ArrayList of N X 3 matrix in this way
The ArrayList is of the form
Ai,Bi,Ci
For example:
1,2,3
2,3,4
1,2,1
2,3,5
so to sort them , first look for all the Ai, if there is a clash like in Ai of 1,2,3 and 1,2,1 ,then look for Bi,if there is a clash ,then look for Ci, and sort them accordingly .
Sorted array
1,2,1
1,2,3
2,3,4
2,3,5
So is there any data structure to sort them without having to write a big long piece of code ?
Those who are asking for my code in comments-->
// RIGHT NOW I HAVEN'T MADE AN N X # MATRIX ,WHAT I HAVE DONE IS TAKEN 3 ARRAYLISTS , yes I WILL CHANGE IT INTO A SINGLE ARRAYLIST OF SIZE N X 3
public class MoSAlgorithmUpdates {
public static void main(String[] args) throws IOException {
//finding no of distict numbers
BufferedReader br = new BufferedReader (new InputStreamReader(System.in));
String str;
//Taking the Array Now
str=br.readLine();
ArrayList<Integer> arr=new ArrayList<Integer>();
StringTokenizer st = new StringTokenizer(str," ");
while(st.hasMoreTokens())
{
arr.add(Integer.parseInt(st.nextToken()));
}
// Total q queries including updates + finding distinct numbers
int Q;
str = br.readLine();
Q = Integer.parseInt(str);
int[] q1=new int[Q];
int[] q2=new int[Q];
int[] q3=new int[Q];
int[] q4=new int[Q];
ArrayList<Integer> query1=new ArrayList<Integer>();// RIGHT NOW I HAVEN'T MADE AN N X # MATRIX ,WHAT I HAVE DONE IS TAKEN 3 ARRAYLISTS , yes I WILL CHANGE IT INTO A SINGLE ARRAYLIST OF SIZE N X 3
ArrayList<Integer> query2=new ArrayList<Integer>();// RIGHT NOW I HAVEN'T MADE AN N X # MATRIX ,WHAT I HAVE DONE IS TAKEN 3 ARRAYLISTS , yes I WILL CHANGE IT INTO A SINGLE ARRAYLIST OF SIZE N X 3
ArrayList<Integer> query3=new ArrayList<Integer>();// RIGHT NOW I HAVEN'T MADE AN N X # MATRIX ,WHAT I HAVE DONE IS TAKEN 3 ARRAYLISTS , yes I WILL CHANGE IT INTO A SINGLE ARRAYLIST OF SIZE N X 3
ArrayList<Integer> update1=new ArrayList<Integer>();
ArrayList<Integer> update2=new ArrayList<Integer>();
ArrayList<Integer> update3=new ArrayList<Integer>();
//int[] update1=new int[Q];
int noofupdates=0;
//noofupdates=time
for(int i2=0;i2<Q;i2++)
{
str=br.readLine();
StringTokenizer st2 = new StringTokenizer(str," ");
q1[i2]=Integer.parseInt(st2.nextToken());
q2[i2]=Integer.parseInt(st2.nextToken());
q3[i2]=Integer.parseInt(st2.nextToken());
if(q1[i2]==1)
{
query1.add(q2[i2]);
query2.add(q3[i2]);
query3.add(noofupdates);
}
else
{
update1.add(q2[i2]);
update2.add(q3[i2]);
noofupdates++;
}
}
}
}
LAST QUERY-->
IN Mo's Algorithm with updates, we arrange the ArrayList by
int sqrt = Math.sqrt(N) // N is the length of ArrayList containing all the
// numbers from which range queries have to be told
now sort the . numbers as
Now let's say L,R,time are for eg
1,3,3
2,3,4
2,1,1
2,3,5
So sorting them by L,R,time returns result as
Sorted array
1,3,3
2,1,1
2,3,4
2,3,5
Now sorting them by has to be done ,how can be that done ? the final output has to be like without square root that is the values L,R,time should not change but sorting has to be done with . How to achieve that -- ?
The final output may look like this depending on the value of N
2,1,1
1,3,3 //Very Imp see this it is sorted
2,3,4
2,3,5
Radix sort
https://en.wikipedia.org/wiki/Radix_sort
You can use default sort method of collections
Collections.sort(yourArrayN2, comparator);
You should define comparator which compares both arrays starting from first elements (we assume that these arrays / lists have the same size; otherwise you will modify the comparator).
Comparator:
public class ListComparator implements Comparator<List<Integer>> {
#Override
public int compare(List<Integer> list1, List<Integer> list2) {
if (list1 == null || list2 == null || list1 == list2) {
throw new IllegalArgumentException();
}
int size = list1.size();
if (size != list2.size()) {
throw new IllegalArgumentException();
}
for (int i = 0; i < size; i++) {
int delta = list1.get(i) - list2.get(i);
if (delta != 0) {
return delta;
}
}
return 0;
}
}
And its usage
public class App {
public void execute() {
List<List<Integer>> list2D = make2DList();
printList2D(list2D);
System.out.println("\n");
Collections.sort(list2D, new ListComparator());
printList2D(list2D);
}
//This is where you create your 2D list. It can be read from file, etc.
private List<List<Integer>> make2DList() {
List<List<Integer>> res = new ArrayList<>(3);
res.add(makeList(1,2,3));
res.add(makeList(2,3,4));
res.add(makeList(1,2,1));
res.add(makeList(2,3,5));
return res;
}
private List<Integer> makeList(Integer ... numbers) {
List<Integer> res = new ArrayList<>();
for (Integer i : numbers) {
res.add(i);
}
return res;
}
private void printList2D(List<List<Integer>> list2D) {
for (List<Integer> list : list2D) {
printList(list);
}
}
private void printList(List<Integer> list) {
int size = list.size();
int lastIndex = size - 1;
for (int i = 0; i < lastIndex; i++) {
System.out.print(list.get(i) + ", ");
}
System.out.print(list.get(lastIndex) + "\n");
}
}
It prints
1, 2, 3
2, 3, 4
1, 2, 1
2, 3, 5
1, 2, 1
1, 2, 3
2, 3, 4
2, 3, 5
My code is intended to take in an array of ints and return an array of ints with a length of twice the original array's length, minus 2.
The returned array should have values 1/3 and 2/3 between any given two values in the original array.
For example input array:
{400, 500, 600}
will return:
{400,433,466,500,533,566,600}
The code I have is as follows:
public static void main(String[] args){
System.out.println("Problem 9 tests");
int[] arr7={300, 400, 500};
System.out.println(highDef(arr7));
System.out.println(" ");
public static int[] highDef(int[] original) {
int[] newarr = new int[original.length*3-2];
newarr[0]=original[0];
int count=0;
while (count!=newarr.length) {
int increment=(original[count+1]-original[count])/3;
newarr[count+1]=original[count]+increment;
newarr[count+2]=original[count]+(count*increment);
count+=1;
}
return newarr;
Haven't looked good enough the first time :)
Here you go:
public static void main(String[] args) {
System.out.println("Problem 9 tests");
int[] arr7 = {300, 400, 500};
System.out.println(Arrays.toString(highDef(arr7)));
System.out.println(" ");
}
public static int[] highDef(int[] original) {
int[] newarr = new int[original.length * 3 - 2];
newarr[original.length * 3 - 3] = original[original.length-1];
for(int i=0; i<original.length-1; i++){
newarr[i*3] = original[i];
int increment = (original[i+1] - original[i])/3;
newarr[i*3+1] = original[i] + increment;
newarr[i*3+2] = original[i] + increment*2;
}
return newarr;
}
With array out of bound exceptions, try to think of the last case.
In your example:
original.length = 3
newarr.length = (original.length * 3) - 2 = 7
while (count!=newarr.length) // this means: while count does not equal to 7. Therefore *Count* value can go upto 6
// imagine the last case, count = 6
newarr[count+2]=original[count]+(count*increment); // the problem is here
// count(6) + 2 = 8, which is out of bounds
same issue with this line: int increment=(original[count+1]-original[count])/3;
count will go upto 6 but original[count+1] = original[7] which is out of bound as well
This question already has answers here:
Java Array, Finding Duplicates
(17 answers)
Closed 8 years ago.
I want to return duplicates in an array.
int[] strArray = new int[] {1,1, 2, 3, 2, 2, 3};
I have used below method to return duplicates.
private static Set<Integer> checkDuplicate(int[] intArray) {
Set<Integer> values = new HashSet<>();
for (int i = 0; i < intArray.length - 1; i++) {
if (intArray[i] == (intArray[i + 1])) {
values.add(intArray[i]);
}
else
System.out.println("not equal");
}
return values;
}
But in this way it checks only the consequtive values.And this needs huge comparisons and time consuming. So is there any better way to do this?
If you do not want to use hashing (HashSet or HashMap), you can first sort the array. And then, you can find duplicates by checking consecutive values. Overall, this method has O(n log n) time complexity.
You may try this example:
import java.util.*;
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int[] strArray = new int[] {1,1, 2, 3, 2, 2, 3, 4, 7, 5, 4};
Set<Integer> duplicates = checkDuplicate(strArray);
System.out.printf("Duplicates: %s\n", duplicates);
}
private static Set<Integer> checkDuplicate(int[] intArray)
{
Set<Integer> duplicates = new HashSet<Integer>();
Set<Integer> tmp = new HashSet<Integer>();
for(Integer i: intArray)
{
if(!tmp.add(i))
{
duplicates.add(i);
}
}
return duplicates;
}
}
If efficiency is what you are looking for then
use HashMap that it has O(1) speed, Also iterate the array of integers in enhanced forloop because it is slightly faster than ordinary forloop
private static Set<Integer> checkDuplicate(int[] intArray) {
HashMap<Integer,Integer> values = new HashMap<Integer,Integer>();
Set<Integer> values2 = new HashSet<Integer>();
for(Integer i : intArray) //0(n)
{
if(values.get(i) != null) //O(1)
values2.add(i);
else
values.put(i, i);
}
return values2;
}
Scan your input and store each number with it's count in a Map<Interger, Integer>. Then loop over the Map and put all keys with value>1 in the resulting Set
See also here: https://stackoverflow.com/a/15217535/461499
You must have to use Collections.frequency
It uses only equals method. If you use any collection Map,Set,List which uses equals method to compare two objects as well as Has collection uses hashCode methods which takes more processing time.
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 1, 4, 4, 1, 5 };
// System.out.println(Arrays.toString(arr));
List<Integer> l = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++) {
l.add(i, arr[i]);
}
// System.out.println(l);
Set<Integer> set = new HashSet<Integer>();
for (int j = 0; j < l.size(); j++) {
if (Collections.frequency(l, l.get(j)) > 1) {
set.add(l.get(j));
}
}
System.out.println(set);
}
O/P :
[1, 4]
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();
}
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;
}
}