find pair of numbers in array that add to given sum - arrays

Question: Given an unsorted array of positive integers, is it possible to find a pair of integers from that array that sum up to a given sum?
Constraints: This should be done in O(n) and in-place (without any external storage like arrays, hash-maps) (you can use extra variables/pointers)
If this is not possible, can there be a proof given for the same?

If you have a sorted array you can find such a pair in O(n) by moving two pointers toward the middle
i = 0
j = n-1
while(i < j){
if (a[i] + a[j] == target) return (i, j);
else if (a[i] + a[j] < target) i += 1;
else if (a[i] + a[j] > target) j -= 1;
}
return NOT_FOUND;
The sorting can be made O(N) if you have a bound on the size of the numbers (or if the the array is already sorted in the first place). Even then, a log n factor is really small and I don't want to bother to shave it off.
proof:
If there is a solution (i*, j*), suppose, without loss of generality, that i reaches i* before j reaches j*. Since for all j' between j* and j we know that a[j'] > a[j*] we can extrapolate that a[i] + a[j'] > a[i*] + a[j*] = target and, therefore, that all the following steps of the algorithm will cause j to decrease until it reaches j* (or an equal value) without giving i a chance to advance forward and "miss" the solution.
The interpretation in the other direction is similar.

An O(N) time and O(1) space solution that works on a sorted array:
Let M be the value you're after. Use two pointers, X and Y. Start X=0 at the beginning and Y=N-1 at the end. Compute the sum sum = array[X] + array[Y]. If sum > M, then decrement Y, otherwise increment X. If the pointers cross, then no solution exists.
You can sort in place to get this for a general array, but I'm not certain there is an O(N) time and O(1) space solution in general.

My solution in Java (Time Complexity O(n)), this will output all the pairs with a given sum
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Map<Integer, Integer> hash = new HashMap<>();
int arr[] = {1,4,2,6,3,8,2,9};
int sum = 5;
for (int i = 0; i < arr.length; i++) {
hash.put(arr[i],i);
}
for (int i = 0; i < arr.length; i++) {
if(hash.containsKey(sum-arr[i])){
//System.out.println(i+ " " + hash.get(sum-arr[i]));
System.out.println(arr[i]+ " " + (sum-arr[i]));
}
}
}
}

This might be possible if the array contains numbers, the upper limit of which is known to you beforehand. Then use counting sort or radix sort(o(n)) and use the algorithm which #PengOne suggested.
Otherwise
I can't think of O(n) solution.But O(nlgn) solution works in this way:-
First sort the array using merge sort or quick sort(for inplace). Find if sum - array_element is there in this sorted array.
One can use binary search for that.
So total time complexity: O(nlgn) + O(lgn) -> O(nlgn).

AS #PengOne mentioned it's not possible in general scheme of things. But if you make some restrictions on i/p data.
all elements are all + or all -, if not then would need to know range (high, low) and made changes.
K, sum of two integers is sparse compared to elements in general.
It's okay to destroy i/p array A[N].
Step 1: Move all elements less than SUM to the beginning of array, say in N Passes we have divided array into [0,K] & [K, N-1] such that [0,K] contains elements <= SUM.
Step 2: Since we know bounds (0 to SUM) we can use radix sort.
Step 3: Use binary search on A[K], one good thing is that if we need to find complementary element we need only look half of array A[K]. so in A[k] we iterate over A[ 0 to K/2 + 1] we need to do binary search in A[i to K].
So total appx. time is, N + K + K/2 lg (K) where K is number of elements btw 0 to Sum in i/p A[N]
Note: if you use #PengOne's approach you can do step3 in K. So total time would be N+2K which is definitely O(N)
We do not use any additional memory but destroy the i/p array which is also not bad since it didn't had any ordering to begin with.

First off, sort the array using radix sort. That'll set you back O(kN). Then proceed as #PengOne suggest.

The following site gives a simple solution using hashset that sees a number and then searches the hashset for given sum-current number
http://www.dsalgo.com/UnsortedTwoSumToK.php

Here's an O(N) algorithm. It relies on an in-place O(N) duplicate removal algorithm, and the existence of a good hash function for the ints in your array.
First, remove all duplicates from the array.
Second, go through the array, and replace each number x with min(x, S-x) where S is the sum you want to reach.
Third, find if there's any duplicates in the array: if 'x' is duplicated, then 'x' and 'S-x' must have occurred in the original array, and you've found your pair.

Use count sort to sort the array O(n).
take two pointers one starts from 0th index of array, and another from end of array say (n-1).
run the loop until low <= high
Sum = arr[low] + arr[high]
if(sum == target)
print low, high
if(sum < target)
low++
if(sum > target)
high--
Step 2 to 10 takes O(n) time, and counting sort takes O(n). So total time complexity will be O(n).

In javascript : This code when n is greater then the time and number of iterations increase. Number of test done by the program will be equal to ((n*(n/2)+n/2) where n is the number of elements.The given sum number is discarded in if (arr[i] + arr[j] === 0) where 0 could be any number given.
var arr = [-4, -3, 3, 4];
var lengtharr = arr.length;
var i = 0;
var j = 1;
var k = 1;
do {
do {
if (arr[i] + arr[j] === 0) { document.write(' Elements arr [' + i + '] [' + j + '] sum 0'); } else { document.write('____'); }
j++;
} while (j < lengtharr);
k++;
j = k;
i++;
} while (i < (lengtharr-1));

Here is a solution witch takes into account duplicate entries. It is written in javascript and runs using sorted and unsorted arrays. The solution runs in O(n) time.
var count_pairs_unsorted = function(_arr,x) {
// setup variables
var asc_arr = [];
var len = _arr.length;
if(!x) x = 0;
var pairs = 0;
var i = -1;
var k = len-1;
if(len<2) return pairs;
// tally all the like numbers into buckets
while(i<k) {
asc_arr[_arr[i]]=-(~(asc_arr[_arr[i]]));
asc_arr[_arr[k]]=-(~(asc_arr[_arr[k]]));
i++;
k--;
}
// odd amount of elements
if(i==k) {
asc_arr[_arr[k]]=-(~(asc_arr[_arr[k]]));
k--;
}
// count all the pairs reducing tallies as you go
while(i<len||k>-1){
var y;
if(i<len){
y = x-_arr[i];
if(asc_arr[y]!=undefined&&(asc_arr[y]+asc_arr[_arr[i]])>1) {
if(_arr[i]==y) {
var comb = 1;
while(--asc_arr[_arr[i]] > 0) {pairs+=(comb++);}
} else pairs+=asc_arr[_arr[i]]*asc_arr[y];
asc_arr[y] = 0;
asc_arr[_arr[i]] = 0;
}
}
if(k>-1) {
y = x-_arr[k];
if(asc_arr[y]!=undefined&&(asc_arr[y]+asc_arr[_arr[k]])>1) {
if(_arr[k]==y) {
var comb = 1;
while(--asc_arr[_arr[k]] > 0) {pairs+=(comb++);}
} else pairs+=asc_arr[_arr[k]]*asc_arr[y];
asc_arr[y] = 0;
asc_arr[_arr[k]] = 0;
}
}
i++;
k--;
}
return pairs;
}
Start at both side of the array and slowly work your way inwards keeping a count of how many times each number is found. Once you reach the midpoint all numbers are tallied and you can now progress both pointers counting the pairs as you go.
It only counts pairs but can be reworked to
find the pairs
find pairs < x
find pairs > x
Enjoy!

Ruby implementation
ar1 = [ 32, 44, 68, 54, 65, 43, 68, 46, 68, 56]
for i in 0..ar1.length-1
t = 100 - ar1[i]
if ar1.include?(t)
s= ar1.count(t)
if s < 2
print s , " - " , t, " , " , ar1[i] , " pair ", i, "\n"
end
end
end

Here is a solution in python:
a = [9, 8, 9, 2, 15, 11, 21, 8, 9, 2, 2, 8, 9, 2, 15, 11, 21, 8, 9, 2, 9, 8, 9, 2, 15, 11, 21, 8, 9, 2, 2, 8, 9, 2, 15, 11, 2, 8, 9, 2, 2, 8,
9, 2, 15, 11, 21, 8, 9, 12, 2, 8, 9, 2, 15, 11, 21, 7, 9, 2, 23, 8, 9, 2, 15, 11, 21, 8, 9, 2, 2, 12, 9, 2, 15, 11, 21, 8, 9, 2, 2,
8, 9, 2, 15, 11, 21, 8, 9, 2, 2, 8, 9, 2, 15, 11, 21, 8, 9, 2, 2, 8, 9, 2, 15, 11, 21, 8, 9, 2, 2, 7.12, 9, 2, 15, 11, 21, 8, 9, 2, 2, 8, 9,
2, 15, 11, 21, 8, 9, 2, 2, 8, 9, 2, 15, 11, 21, 8, 9, 2, 2, 8, 9, 2, 15, 11, 21, 8, 9, 2, 2, 8, 9, 2, 15, 11, 21, 8, 0.87, 78]
i = 0
j = len(a) - 1
my_sum = 8
finded_numbers = ()
iterations = 0
while(OK):
iterations += 1
if (i < j):
i += 1
if (i == j):
if (i == 0):
OK = False
break
i = 0
j -= 1
if (a[i] + a[j] == my_sum):
finded_numbers = (a[i], a[j])
OK = False
print finded_numbers
print iterations

I was asked this same question during an interview, and this is the scheme I had in mind. There's an improvement left to do, to permit negative numbers, but it would only be necessary to modify the indexes. Space-wise ain't good, but I believe running time here would be O(N)+O(N)+O(subset of N) -> O(N). I may be wrong.
void find_sum(int *array_numbers, int x){
int i, freq, n_numbers;
int array_freq[x+1]= {0}; // x + 1 as there could be 0’s as well
if(array_numbers)
{
n_numbers = (int) sizeof(array_numbers);
for(i=0; i<n_numbers;i++){ array_freq[array_numbers[i]]++; } //O(N)
for(i=0; i<n_numbers;i++)
{ //O(N)
if ((array_freq[x-array_numbers[i]] > 0)&&(array_freq[array_numbers[i]] > 0)&&(array_numbers[i]!=(x/2)))
{
freq = array_freq[x-array_numbers[i]] * array_freq[array_numbers[i]];
printf(“-{%d,%d} %d times\n”,array_numbers[i],x-array_numbers[i],freq );
// “-{3, 7} 6 times” if there’s 3 ‘7’s and 2 ‘3’s
array_freq[array_numbers[i]]=0;
array_freq[x-array_numbers[i]]=0; // doing this we don’t get them repeated
}
} // end loop
if ((x%2)=0)
{
freq = array_freq[x/2];
n_numbers=0;
for(i=1; i<freq;i++)
{ //O([size-k subset])
n_numbers+= (freq-i);
}
printf(“-{%d,%d} %d times\n”,x/2,x/2,n_numbers);
}
return;
}else{
return; // Incoming NULL array
printf(“nothing to do here, bad pointer\n”);
}
}
Critics are welcomed.

In java, this is depends on max number in array.
it returns an int[] having the indexes of two elements.
it is O(N).
public static int[] twoSum(final int[] nums, int target) {
int[] r = new int[2];
r[0] = -1;
r[1] = -1;
int[] vIndex = new int[0Xffff];
for (int i = 0; i < nums.length; i++) {
int delta = 0Xfff;
int gapIndex = target - nums[i] + delta;
if (vIndex[gapIndex] != 0) {
r[0] = vIndex[gapIndex];
r[1] = i + 1;
return r;
} else {
vIndex[nums[i] + delta] = i + 1;
}
}
return r;
}

First you should find reverse array => sum minus actual array
then check whether any element from these new array exist in the actual array.
const arr = [0, 1, 2, 6];
const sum = 8;
let isPairExist = arr
.map(item => sum - item) // [8, 7, 6, 2];
.find((item, index) => {
arr.splice(0, 1); // an element should pair with another element
return arr.find(x => x === item);
})
? true : false;
console.log(isPairExist);

Naïve double loop printout with O(n x n) performance can be improved to linear O(n) performance using O(n) memory for Hash Table as follows:
void TwoIntegersSum(int[] given, int sum)
{
Hashtable ht = new Hashtable();
for (int i = 0; i < given.Length; i++)
if (ht.Contains(sum - given[i]))
Console.WriteLine("{0} + {1}", given[i], sum - given[i]);
else
ht.Add(given[i], sum - given[i]);
Console.Read();
}

def pair_sum(arr,k):
counter = 0
lookup = set()
for num in arr:
if k-num in lookup:
counter+=1
else:
lookup.add(num)
return counter
pass
pair_sum([1,3,2,2],4)
The solution in python

Not guaranteed to be possible; how is the given sum selected?
Example: unsorted array of integers
2, 6, 4, 8, 12, 10
Given sum:
7
??

Related

Interview Question - Find the Max difference of Two elements in the Array in less than O(n^2) - the Lower element should precede the Greater element

During an interview, I've been asked the following Question:
You're given an array of integer numbers.
Find the maximum difference between two elements arr[j] - arr[i]
for any sub array in the array, so that j>i.
For example:
array = {20,18,45,78,3,65,55}, max diff is 65 - 3 = 62.
array = {20,8,45,78,3,65,55}, max diff is 78 - 8 = 70.
Here is the solution I come up with:
private static int calculateProfit() {
int[] arr = {20, 18, 45, 78, 3, 65, 55};
int maxProfit = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = arr.length - 1; j > 0; j--) {
if (arr[i] < arr[j] && i < j) {
maxProfit = Math.max(arr[j] - arr[i], maxProfit);
}
}
}
return maxProfit; // ans: (65 - 3) = 62
}
The problem is that it runs in O(n^2). How it can be done with a better time complexity?
This problem can be solved in a linear time O(n), with a single run through the given array.
We need to declare only a couple of local variables, no data additional data structures required, space complexity is O(1).
These are the variables we need to track:
min - the lowest value encountered so far;
max - the highest encountered value;
maxProfit - maximal profit that can be achieved at the moment.
While declaring these variables, we can either initialize min to Integer.MAX_VALUE and max to Integer.MIN_VALUE, or initialize both with the value of the first element in the array (this element should be present because the array needs to have at least two elements, otherwise the task has no sense).
And here is a couple of caveats:
Since max element can not precede the min element, when a new min element is encountered (when the current element is less than min) the max element also needs to be reinitialized (with Integer.MIN_VALUE or with the value of the current element depending on the strategy you've chosen at the beginning).
maxProfit should be checked against the difference between max and min each time when a new max has been encountered.
That's how it might be implemented:
public static int calculateProfit(int[] arr) {
if (arr.length < 2) return -1; // incorrect input
int max = arr[0];
int min = arr[0];
int maxProfit = 0;
for (int i = 1; i < arr.length; i++) {
int next = arr[i];
if (next > max) {
max = next;
maxProfit = Math.max(max - min, maxProfit);
} else if (next < min){
min = next;
max = next;
}
}
return maxProfit;
}
main()
public static void main(String[] args) {
System.out.println(calculateProfit(new int[]{1, 2, 3, 4, 10}));
System.out.println(calculateProfit(new int[]{1, 10, -10, 4, 8}));
System.out.println(calculateProfit(new int[]{5, 8, 12, 1, 9}));
System.out.println(calculateProfit(new int[]{20, 18, 45, 78, 3, 65, 55}));
}
Output:
9 // [1, 2, 3, 4, 10] -> 10 - 1 = 9
18 // [1, 10, -10, 4, 8] -> 8 - (-10) = 18
8 // [5, 8, 12, 1, 9] -> 9 - 1 = 8
62 // [20, 18, 45, 78, 3, 65, 55] -> 65 - 3 = 62
Start by finding the first possible solution. This is easy. Scan left-to-right. Track p for the index of the lowest value seen so far. As soon as you see a new non-descending value, set q to that index and goto step 2:
[8, 5, 2, 2, 4, ...]
[ D D -, I ] # Look for first increasing value
[ p q ] # arr[p] < arr[q] and p < q
Now continue looping over the array, looking for an improvement to the solution. The new wrinkle is tracking a u, the index of a value smaller than arr[p] but is unused because it is to the right of q:
[8, 5, 2, 2, 4, 3, 1, ...]
[ p q u ] # arr[u] < arr[p] but u > q
For each new value in the loop, update the solution. If the new i/u difference is bigger than the p/q solution, it becomes the new best:
[8, 5, 2, 2, 4, 3, 1, 2, X, ...]
[ p q u i, ...]
\...../ Previous best solution
\-----/ Potential new best

Finding how many pairs of numbers are in reach of a distance D in a sequence of integers

Let's have an increasing sequence of distinct non-negative integers {0, 2, 3, 4, 7, 10, 12}. What's the fastest way of telling how many pairs are at most a distance let's say D = 3 from each other?
For example here it would be: [0, 2], [0, 3], [2, 3], [2, 4], [3, 4], [4, 7], [7, 10], [10, 12], so 8.
My shot at this:
int arr[] = {0, 2, 3, 4, 7, 10, 12};
int arrLength = 7;
int k = 1;
int D = 3;
int sum = 0;
for (int i = 0; i < arrLength;) {
if (i + k < arrLength && arr[i + k] - arr[i] <= D) {
sum++;
k++;
}
else {
i++;
k = 1;
}
}
printf("Number of pairs: %d\n", sum);
It takes too much time for larger arrays. Is there any other way of exploiting the fact, that:
The sequence is always increasing.
There can't be two same numbers.
We don't need to print out the exact pairs, just the number of them.
The integers can't be negative.
We could somehow share already computed pairs to other iterations.
The else clause is very pessimistic. You don't need to reset k to 1. It is obvious that a[i+1] forms the pair with all values in the [i+2, i+k) range. Consider a sliding window, along the lines of (untested)
i = 0;
j = 1;
while (i < arrLen) {
while (j < arrlen && a[j] - a[i] <= D) {
j++;
}
i++;
sum += j - i;
if (i == j) {
j++;
}
}
with a linear time complexity.
You can do it by dynamic programming. If M(n) is number of specified pairs, we will have M(n) = M(n-1) + number of pairs of A[0..n-2] with A[n-1] which have less than D. To find the last part of the recursion, it can be computed by log(n) as they are sorted. Hence, the time complexity of this algorithm is T(n) = T(n-1) + log(n) = O(n log(n)).

Arrange odd numbers first, followed by even number. order of odd even should not be changed

Below is code snippet to reorder odd numbers followed by even numbers without changing the order of even/odd numbers in original array.
input - {1, 4, 8, 3, 9, 12, 7}
output - {1, 3, 9, 7, 4, 8, 12}
Can We improve this from O(n2) in space (without using extra space)?
public static void reOrder(int[] arr) {
int evenIndex = arr.length;
for(int i=0; i < arr.length;i++) {
if(arr[i] % 2 == 0 && evenIndex == arr.length) //even index
evenIndex = i;
else if( arr[i] % 2 != 0 ) {
if(i > evenIndex ) {
shift (arr, evenIndex , i);
evenIndex ++;
}
}
}
}
static void shift(int[] arr, int evenIndex, int endIndex) {
int temp = arr[endIndex];
for(int i = endIndex; i > evenIndex ;i --) {
arr[i] = arr[i-1];
}
arr[evenIndex] = temp;
}
Stable partition is what you are looking for
std::vector<int> l = {1, 4, 8, 3, 9, 12, 7};
std::stable_partition(l.begin(), l.end(),
[](int A) -> bool {
return (A & 1) == 1; // A is odd
});
Exactly N applications of the predicate and O(N) swaps if there is enough extra memory. O(N log N) swaps and O(N) applications of the predicate
Question on how stable partition works along with its complexity.
A stable quick sort, for example, will use a stable partitioning under the hood. Check out the accepted answer here for an O(n*log(n)) implementation of a stable partition algorithm that is beautifully recursive.
You didn't specify any language tag, so I'll answer using python (just because it's quicker for me to use it at the moment).
If you only care about space complexity you can do something like this:
l = [1, 4, 8, 3, 9, 12, 7]
even_index = -1
for index in range(0, len(l)):
if (l[index] % 2) == 0:
if even_index == -1:
even_index = index
else:
if (index > 0) and (even_index > -1):
num = l[index]
l.insert(even_index, num)
del l[index + 1]
even_index += 1
print(l)
You keep an index of where the first even number is and insert the odd number as you find them going through the list. Then you remove the odd number at the "old" index (which is now increased by 1).
I think the space complexity is what you need, but the time complexity can be improved.
For example, in Python a collections.deque is probably better in this case, but time complexity was not a priority.

Algorithm: Given an array A of numbers, create an array B where B[i] = sum(A[j]: A[j] <= A[i])

Example: A = [4, 1, 3, 2, 3, 3]. Then we'd get B = [16, 1, 12, 3, 12, 12].
Approach 1: For each i, just search through A and sum up the numbers that are less than or equal to A[i]. Roughly speaking, this requires transversing through A n times, so it'll take O(n^2) time.
Approach 2: Sort A to get A', and then just find the cumsum of A'. This requires transversing through A' only once. So the overall running time is just the sort, O(n log n).
However, this doesn't work when there are ties. For the example above, we get A' = [1, 2, 3, 3, 3, 6], so cumsum(A') = [1, 3, 6, 9, 12, 16], which is not the same as B (sorted).
Is there a way to fix this so that it still runs in O(n log n)?
One way to do that with modern languages is to use dictionnary :
A=random_integers(1,10,10)
SA=sorted(A) #O(n log n)
CSA=cumsum(SA) #O(n)
I=dict(zip(SA,CSA)) #O(n)
B=[I[x] for x in A] #O(n)
When building the dictionnary, the last value encountered replace the existing one, so at least it fits the good one.
That gives :
[7 5 4 1 4 2 6 7 8 2]
[1 2 2 4 4 5 6 7 7 8]
[1 3 5 9 13 18 24 31 38 46]
{1:1, 2:5, 4:13, 5:18, 6:24, 7:38, 8:46}
[38 18 13 1 13 5 24 38 46 5]
The better approach could have been to sort the A to A' = [1, 3, 6, 9, 12, 16], then find the total sum of the integers and instead of cumsum, iterate over the array like below:
B[A.length-1] = sum;
for(int i=A.length-2; i=0; i++){
if(A[i]!=A[i+1]){
B[i] = sum - B[i+1];
}
else{
B[i] = B[i+1];
}
}
Okay, if you allow for O(n log n) Then here is a very simple approach to achieve it:
Copy A to A' and sort A', O(n lg n)
Calculate Prefix Sum of A', store them in S, O(n)
Loop through A, for each element A_i, binary search the largest index j in A' such that A'[j] >= A_i, Ans[i] = S[j]
Ans is the array you want
Below is a sample C++ code illustrate the idea
#include<bits/stdc++.h>
using namespace std;
int A[6] = {4, 1, 3, 2, 3, 3}, B[6], SUM[6] = {0}, ANS[6];
int main(){
for(int i=0; i<6; i++) B[i] = A[i];
sort(B, B+6);
for(int i=0; i<6; i++) SUM[i] = (i? SUM[i-1]:0) + B[i];
for(int i=0; i<6;i++){
int j = upper_bound(B,B+6, A[i]) - B;
ANS[i] = SUM[j-1];
printf("%d ", ANS[i]);
}
puts("");
return 0;
}
In the sorted approach, before storing the result, find all the elements with same value (which are now all consecutive, so this is the same traversal as you would have already been doing) and handle them all together: calculate the sum (same for all), then record the (same) result for each of them.
I have easy approach to doing this in o(nlogn).
sort the array with respect to their value in increasing order.In sorting index of element should go with element.for sorting in java you can use inbuilt function
java.util.Arrays.sort(input, new java.util.Comparator<int[]>() {
public int compare(int[] a, int[] b) {
return Double.compare(a[1], b[1]);
}
});
create a temp array which will contain answer.
calculate sum of all element in sorted array.
traverse sorted array from back to front.
maintain count for contiguous similar number.
when get different value from next value update sum with sum-count*nextvalue.
store the sum at index of current value;
Here is my java code
class Solution
{
public static void main (String[] args) throws java.lang.Exception
{
int[][] input={{0,4}, {1,1}, {2,3}, {3,2}, {4,3}, {5,3
//sort one column with respect to other column in 2d array
java.util.Arrays.sort(input, new java.util.Comparator<int[]>() {
public int compare(int[] a, int[] b) {
return Double.compare(a[1], b[1]);
}
});
int[] temp=new int[6]; //Answer array
int sum=0;
for(int i=0;i<6;i++){
sum=sum+input[i][1];
}
int count=1;
temp[input[5][0]]=sum;
for(int i=4;i>=0;i--){
if(input[i][1]==input[i+1][1]){
count++;
temp[input[i][0]]=sum;
}
else{
sum=sum-(count*input[i+1][1]);
temp[input[i][0]]=sum;
count=1;
}
}
for(int i=0;i<6;i++)
System.out.print(temp[i]+" ");
}
}

Algorithm - Find existence of a 2d array in another 2d array

I came across this question while in an interview and i am unable to find the best way to do it.
The question says, there are two 2d arrays, one is bigger than the other.
Lets say,
Array_1 = [[1,2],
[5,6]]
and
Array_2 = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12]]
Since, here the Array 2 contains Array 1, the algo should return true. Otherwise, false.
The size of the array can be anything.
Try this.
function Test() {
var x = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]];
var y = [[6, 7], [10, 12]];
for (i = 0; i < x.length; i++) {
for (j = 0; j < x[i].length; j++) {
if (x[i][j] == y[0][0])
if (findMatch(x, y, i, j)) {
console.log("Match Found");
return true;
}
}
}
console.log("Not found");
return false;
}
function findMatch(x, y, i, j) {
var b = true;
for (k = i; k < y.length; k++) {
for (n = j; n < y[k].length; n++) {
if (y[k - i][n - j] != x[k][n]) {
b = false;
break;
}
}
}
return b;
}
Note that this doesn't match if the smaller array is rotated inside the big array.(Written in javaScript)
I would fill in the smaller array to the bigger dimensions with null values (or with NaN), convert to 1D and truncate/strip the unnecessary nulls :
array_1 = [1, 2, null, null, 5, 6]
array_2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
then compare the 1D arrays, while skipping the null values - this would be O(n*m) in the worst case (such as [1,1,1,2] vs [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]), and it would be O(n) in the best case (if every number in the bigger array was different)
Edit: more logic is needed to ensure comparison only within the complete rows of the bigger array, not across rows...
I guess you could convert the arrays to dictionaries of positions and figure out a bit more complicated and faster algorithm if you need to do multiple comparisons...
You could also rotate the smaller array if needed, e.g.:
array_1_270 = [6, 2, null, null, 1, 5]
You can try aho-corasick algorithm for 2 dimension. Aho-corasick algorithm is the fastest multiple pattern matching. Here is a similar question:is there any paper or an explanation on how to implement a two dimensional KMP?
Maybe a little simpler in Python 2.6
def check():
small=[[1,2],[5,6]] #matches upper left corner
smallrows = len(small) #rows = 2
smallcols = len(small[0]) #cols = 2
big=[[1,2,3,4],[5,6,7,8],[9,10,11,12]]
bigrows = len(big) #rows = 3
bigcols = len(big[0]) #cols = 4
for i in range(bigrows-smallrows+1): #i is number row steps
for j in range(bigcols-smallcols+1): #j is number col steps
flag = 0
for k in range(smallrows):
for l in range(smallcols):
if big[i+k][j+l] != small[k][l]:
flag = 1
continue
if flag == 0:
return(True)
return(False)
print check()

Resources