find the longest intersection of two integer arrays - java

I have this problem but don't know what's best way to solve it in term of time complexity and space complexity.
Suppose I have two integer arrays
a={1,2,3,4,5}
b={2,3,4,5,6}
and of course they not necessarily to be sorted.
So the question is how to find 2,3,4,5? It better to have some code. Thanks in advance

why do we need DP here? question says find the longest intersection, not any intersection. am i missing a point?
There are lot of solutions to this.
int [] a = {...}; // n elements
int [] b = {...}; // m elements
You can store one array in a dictionary and for each element in the other array check the dictionary. That O(n). THis will cost you more space due to dictionary. and it s not in-place
Another solution would be for each element in a, you can do a linear search on b. which is O(n.m)
Another would be ;if you sort both of the arrays. Then for each element in one array do a binary search in another array. You will find the intersection of two. and this will be mlogn + nlogn or nlogm + mlogm
do we really need DP here?

This is actually a pretty popular programming problem. There is a dynamic programming approach to solving it. You can check out more about it at http://en.wikipedia.org/wiki/Longest_common_subsequence_problem

I hope this link will solve your problem.
You have to write a common function which will display common numbers in two arrays.
And it use only one for loop .Thats why its complexity will be just O(N).
Find common numbers.
Code is in C . But i hope you can understand the logic.

At first we should sort our arrays, at second we should use binary search to finde a intersection of thise arrays.
Why? Because if we semple will searching intersection, without sort, our algorithm laboriousness will be N^2, but if we sort array before searching, totaly we will have [log_2(N)N + ( N(log_2(N)) up to N^2 )].
My method is useful for majority of samples

Related

Java - find all combinations of three numbers in sorted array that have a sum smaller than a number

The title is a mouthful so I will explain further. This is a question out of a practice test for my introduction to computer science course. Most of the questions I was able to solve by myself or find a solution online, but not for this one.
You are given a sorted array (int[] arr) of unique integers (positive and negative). You must find how many triplets (combinations of three numbers in the array) have a sum that is less than a given number (int num).
The method signature is:
public static int countTriplets (int [] arr, int num)
The catch is that it must be done with the lowest possible time complexity. If I understand correctly, iterating over all the possible combinations with nested for loops would give me a time complexity of O(n^3). However, I can't think of any other solution.
I should also mention that the array should be used as an array, without using other Java classes like ArrayList.
Any help is appreciated. It doesn't have to be a complete solution in code, even just a general idea of how to solve this.
You can try two approaches for this 3-sum smaller problem:
Since the array is already sorted, you can jump right in with either algorithm.
Binary search approach O(n^2logn)
Two pointer approach : O(n^2)
I would attempt the two-pointer approach. Take a look on Leetcode for 2-sum and 3-sum problem since this is a variation of it. Best of luck!

Java efficiency (Calling method)

I'm writing a method that finds intersection of given arrays.
Since I had to iterate both arrays, I was thinking of using
if(arr2.length > arr1.length){
intersection(arr2, arr1);
}
The reason I came up with this idea was that it seemed to me to be the better way to reduce the length of code for handling arrays that have different length.
As a newbie to programming, I'm wondering if there is any other suggestion.
Put your array in a list:
List a = List.asArray(arr1);
(ref: https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#asList(T...)
And use the suggestion here to find the intersection:
How to do union, intersect, difference and reverse data in java

Java algorithm to "multiply" two lists of lists ((A),(B))*((C,C),(D,D))==((A,C,C),(A,D,D),(B,C,C),(B,D,D))

I have two lists of lists, the sublists represent paths. I want to find all paths.
List<List<E>> pathList1
List<List<E>> pathList2
The naive solution of course:
List<List<E>> result = new ArrayList<List<E>>();
for(List<E> p1 : pathList1) {
for(List<E> p2: pathList2) {
List<E> newList = new ArrayList<E>(p1.size()+p2.size());
newList.addAll(p1);
newList.addAll(p2);
result.add(newList);
}
}
Unrelated theoretical question
I've recently learned about time complexity. So this is a self check, I hope someone can comment if I am correct.
Let N = num lists in pathList1
Let M = num lists in pathList2
Let X = average length of path in pathList1
Let Y = average length of path in pathList2
So if asked "What is the complexity of this function?" I would give
~O(NM(X + Y))
I was wondering if there was a faster way to do this?
Maybe a better data structure?
Do it concurrently?
Make some sort of "future" of sorts and return that instead? (Full disclosure, I'm 97% ignorant on futures).
I'm open to clever tricks and unique solutions, or purely practical.
Thanks.
You can take a look at guava
in particular to the Sets#cartesianProduct
i.e. you can do something of this sort:
Sets.cartesianProduct(ImmutableList.of(
ImmutableSet.of(Sets.newHashSet(pathList1)),
ImmutableSet.of(Sets.newHashSet(pathList2)))
I'm confused by what your goal is exactly.
If you have the following lists of paths "(A,B,C)(D,E)" and "(C,D)(A,B)"
then your current code would return
"(A,B,C,C,D),(D,E,C,D),(A,B,C,A,B),(D,E,A,B)"
Is that what you want? That's not all paths, that's all combinations of paths.
A list of all paths would be
"(A,B,C)(D,E)(C,D)(A,B)"
Which could be performed in simple O(N) time.
Also with Big-O notation we usually aren't concerned about the individual variables, only the overall scale of the problem complexity. It is generally written purely as a function of a single variable, n, which is the number of elements.
But if you want to "multiply" the two lists, each element of one against the other, then its going to be O(n^2) and there's not really any faster way.

find if there exists a common element in 2 arrays

Given two arrays of integers, how can you efficiently find out if the two arrays have an element in common?
Can somebody come up with a better space complexity than this (I would appreciate pointing errors in the program too, thanks!!).
Is it possible to solve this using a XOR?
public boolean findcommon(int[] arr1, int[] arr2) {
Set<int> s = new Hashset<int>();
for(int i=0;i<arr1.length;i++) {
if(!s.contains(arr1[i]))
s.add(arr1[i]);
}
for(int i=0;i<arr2.length;i++) {
if(s.contains(arr2[i]))
return true;
}
return false;
}
Since you are asking for a more space efficient solution:
When you accept a runtime of O(n log n) and are allowed to change the arrays, you could sort them and then do a linear pass to find the common elements.
If you only need to do it ONCE, then you can't do better than time complexity O(n+m) where n and m are the respective lengths of arrays. You have to go through the input in both arrays, there is no choice (how else will you look at all the input?), so just the input processing will have that complexity, there is no point in doing something more efficient. If you need to keep searching as the arrays grow, that's a different discussion.
So the question with your suggested way of implementing comes down to how long does "contains" take? Since you're using a Hashset, contains is constant time O(1), so you get to O(n) to create the hashset and O(m) to verify elements in the second array.
Put together, O(n+m). Good enough ;)
If you're looking for improved space complexity, you first of all need to be able to make changes to the original arrays. But I don't think there's any way to use less additional space than O(n) and still perform in O(n+m) time.
Note: I'm not sure what XOR you are thinking of. If you're thinking of bit-wise or logical XOR, there's no use for it here. If you're thinking of Set XOR, it doesn't matter if it's logically useful or not, as it's not in the implementation of Java Sets, so you would still have to roll your own.
Given that your solution only attempts to find if there is an element that exists in both arrays, the following is code that will do it for you:
public boolean findCommon(int[] arr1, int[] arr2) {
HashTable hash = new HashTable();
for (item : arr1){
if !(hash.containsKey(item)){
hash.put(item, "foo");
}
}
for (item : arr2){
if (hash.containsKey(item)){
return(true);
}
}
return(false);
}
This does still have a worst case complexity of O(n) for two arrays which do not share single element. If as is suggested by your initial question what you're worried about is Space Complexity (eg, you'd be happy to accept a performance hit if you didn't have to store the HashTable), you could go for something along these lines:
public boolean findCommon(int[] arr1, int[] arr2){
for (item : arr1){
for(item2 : arr2){
if(item ==item2){
return(true);
}
}
}
return(false);
}
That would solve your Space Complexity issue, but would have the (objectively terrible) Time Complexity of O(n^2).
This could be simplified if you were to put more parameters around it (Say you happen to know that at least one of the arrays is sorted, or better yet, both are sorted).
But in the wildcard example you asked I believe it really will come down to O(n) with a HashTable for Space Complexity, or O(n^2) with less space complexity.
You can improve space occupation (this is the question right?) with an algoritm of order O(n*m). Just take every pair of elements and compare them... This is awful in time but does not use any additional memory. Otherwise you could sort the two array in place (if you are allowed to modify them) and find the common elements in O(max(n,m)).

Java Search an array for a matching string

how can I optimize the following:
final String[] longStringArray = {"1","2","3".....,"9999999"};
String searchingFor = "9999998"
for(String s : longStringArray)
{
if(searchingFor.equals(s))
{
//After 9999998 iterations finally found it
// Do the rest of stuff here (not relevant to the string/array)
}
}
NOTE: The longStringArray is only searched once per runtime & is not sorted & is different every other time I run the program.
Im sure there is a way to improve the worst case performance here, but I cant seem to find it...
P.S. Also would appreciate a solution, where string searchingFor does not exist in the array longStringArray.
Thank you.
Well, if you have to use an array, and you don't know if it's sorted, and you're only going to do one lookup, it's always going to be an O(N) operation. There's nothing you can do about that, because any optimization step would be at least O(N) to start with - e.g. populating a set or sorting the array.
Other options though:
If the array is sorted, you could perform a binary search. This will turn each lookup into an O(log N) operation.
If you're going to do more than one search, consider using a HashSet<String>. This will turn each lookup into an O(1) operation (assuming few collisions).
import org.apache.commons.lang.ArrayUtils;
ArrayUtils.indexOf(array, string);
ArrayUtils documentation
You can create a second array with the hash codes of the string and binary search on that.
You will have to sort the hash array and move the elements of the original array accordingly. This way you will end up with extremely fast searching capabilities but it's going to be kept ordered, so inserting new elements takes resources.
The most optimal would be implementing a binary tree or a B-tree, if you have really so much data and you have to handle inserts it's worth it.
Arrays.asList(longStringArray).contains(searchingFor)

Categories

Resources