Interview Question: Replacing two arrays's place in memory - arrays

Given two consecutive arrays, A and B. They look something like
int AandB[] = {a1,a2,...,am,b1,b2,...,bn};
You need to write a program that would switch the order of arrays A and B in the memory, so that B would appear before A. In our example, AandB should become
int AandB[] = {b1,b2,...,bn,a1,...,am};
What's the most efficient way to do that?

Three array reverses:
(a1 a2 a3 a4 a5 b1 b2 b3)
b3 b2 b1 a5 a4 a3 a2 a1
(b3 b2 b1)a5 a4 a3 a2 a1
b1 b2 b3 a5 a4 a3 a2 a1
b1 b2 b3(a5 a4 a3 a2 a1)
b1 b2 b3 a1 a2 a3 a4 a5
Expressed using a "rev" function that takes a start and end:
rev(AandB, 0, n+m)
rev(AandB, 0, m)
rev(AandB, m, n)
For rev (omitting types, etc. for clarity):
rev(x, i, j) {
j--; // j points to one after the subarray we're reversing
while (i < j) {
tmp = x[i];
x[i] = x[j];
x[j] = tmp;
i++;
j--;
}
}

My answer:
First, I'm assuming wlog that m<n.
Since every permutation can be decomposed into disjoint cycles, so can the permutation which takes a1,...,am,b1,..,bn to b1,..,bn,a1,...,am. And since given an index i, it is easy to calculate p(i) (assume wlog that m<n, then if i<=m, we have p(i)=n+i, if i>m we have p(i)=i-m).
We can start with AandB[i] and move its value to p(i)=j, then, take the value in AandB[j] and move it to p(j), etc. Since permutations can be decompose into disjoint cycles, we'll end up in i.
We only need to keep track of which elements did we already move. It is possible to prove that in our case, no cycle in the permutation will contain two consecutive elements of A, so I think it is enough to keep track of how many elements of A have we ordered.
Another simple option which is not as efficient is to note that
given {a1,...,am,b1,...bn}, it is possible to replace a1..am with b(n-m)..b(n), getting {b(n-m)...b(n),b(1)..b(m),a1..am}. And now by recursion, solve the same problem for the first n elements of your array. But this is probably not so efficient.
There are some more details which I omitted, but anyhow the interviewer told me that it's not the way to go, and there's some very clever solution that is also very simple.

The transformation you want to do is essentially a circular shift by n (or by m, depending on the direction of the shift).
E.g., we have 1 2 3 4 5 6 7 a b c (I use letters and numbers to separate two arrays)
During this transformation, 1 will move to the position of 4, 4 will move to 7, 7 to c, c to 3, 3 to 6, etc. Eventually, we'll return to the position 1, from which started.
So, moving one number at the time, we completed it.
The only trick is that sometimes we'll return to 1 before completing whole transformation. Like in the case 1 2 a b c d, the positions will be 1 -> a -> c -> 1. In this case, we'll need to start from 2 and repeat operation.
You can notice that amount of repetitions we need is a greatest common divisor of n and m.
So, the code could look like
int repetitions = GCD(n, m);
int size = n + m;
for (int i = 0; i < repetitions; ++i) {
int current_number = a[i];
int j = i;
do {
j = (j + n) % size;
int tmp = current_number;
current_number = a[j];
a[j] = tmp;
} while (j != i);
}
Greatest common divisor can be easily computed in O(logn) with well-known recursive formula.
edit
It does work, I tried in Java. I only changed data type to string for ease of representation.
String[] a = {"1", "2", "3", "4", "5", "6", "a", "b", "c"};
int n = 3;
int m = 6;
// code from above...
System.out.println(Arrays.toString(a));
And Euclid's formula:
int GCD(int a, int b) {
if (a == 0) {
return b;
}
return GCD(b % a, a);
}

Well, thinking while typing here...
I'm assuming by "in memory" you can't cheat by creating one or more new arrays, even as temporaries. I will also assume that you can have a single temporary variable (otherwise swapping contents would get really tricky).
It looks like your two sub-arrays can be different sizes, so you can't just swap a1 with b1 and a2 with b2, etc.
So you need to figure out where the "a" array elements will start first. You do that by finding "n". Then you'd have to repeatedly save the first remaining "a" element, and put the first remaining "b" element there.
Now here's where it gets tricky. You need to get the save "a" element into its rightful spot, but that may contain an unswapped element. The easiest thing to do would probably be to just shift up all the remaining elements by one, and put your saved "a" at the end. If you do that repeatedly, you'll end up with everything in the right place. That's a lot of shifting though if the arrays are large.
I believe a slightly more sophisiticated algorithim could just do shifting for the elements in the delta (the first "q" elelments, where "q" is the delta between your array sizes) and only while working in the delta area. After that it would just be simple swaps.

we can use array_merge from php.
use array_splice() first to split these arrays and then use the above function. This is for php.

Related

Recover original array from all subsets

You are given all subset sums of an array. You are then supposed to recover the original array from the subset sums provided.
Every element in the original array is guaranteed to be non-negative and less than 10^5. There are no more than 20 elements in the original array. The original array is also sorted. The input is guaranteed to be valid.
Example 1
If the subset sums provided are this:
0 1 5 6 6 7 11 12
We can quickly deduce that the size of the original array is 3 since there are 8 (2^3) subsets. The output (i.e original array) for the above input is this:
1 5 6
Example 2
Input:
0 1 1 2 8 9 9 10
Output:
1 1 8
What I Tried
Since all elements are guaranteed to be non-negative, the largest integer in the input must be the total of the array. However, I am not sure as to how do I proceed from there. By logic, I thought that the next (2^2 - 1) largest subset sums must include all except one element from the array.
However, the above logic does not work when the original array is this:
1 1 8
That's why I am stuck and am not sure on how to proceed on.
Say S is the subset sum array and A is the original array. I'm assuming S is sorted.
|A| = log2(|S|)
S[0] = 0
S[1] = A[0]
S[2] = A[1]
S[3] = EITHER A[2] OR A[0] + A[1].
In general, S[i] for i >= 3 is either an element of A or a combination of the elements of A that you've already encountered. When processing S, skip once per combination of known elements of A that generate a given number, add any remaining numbers to A. Stop when A gets to the right size.
E.g., if A=[1,2,7,8,9] then S will include [1,2,1+2=3,...,1+8=9, 2+7=9,9,...]. When processing S we skip over two 9s because of 1+8 and 2+7, then see a third 9 which we know must belong to A.
E.g., if S=[0,1,1,2,8,9,9,10] then we know A has 3 elements, that the first 2 elements of A are [1,1], when we get to 2 we skip it because 1+1=2, we append 8 and we're done because we have 3 elements.
Here's an easy algorithm that doesn't require finding which subset sums to a given number.
S ← input sequence
X ← empty sequence
While S has a non-zero element:
d ← second smallest element of S (the smallest one is always zero)
Insert d in X
N ← empty sequence
While S is not empty:
z ← smallest element of S
Remove both z and z+d from S (if S does not contain z+d, it's an error; remove only one instance of both z and z+d if there are several).
Insert z in N.
S ← N
Output X.
I revisited this question a few years later and finally managed to solve it! The approach that I've used to tackle this problem is the same as what Dave had devised earlier. Dave gave a pretty concrete explanation so I'll just add on some details and append my commented C++ code so that it's a bit more clear;
Excluding the empty set, the two smallest elements in S has to be the two smallest elements in A. This is because every element is guaranteed to be non-negative. Having known the values of A[0] and A[1], we have something tangible to work and build bottom-up with.
Following which, any new element in S can either be a summation of the previous elements we have confirmed to be in A or it can an entirely new element in A. (i.e S[3] = A[0] + A[1] or S[3] = A[2]) To keep track of this, we can use a frequency table such as an unordered_map<int, int> in C++. We then repeat this process for S[4], S[5]... to continue filling up A.
To prune our search space, we can stop the moment the size of A corresponds with the size of S. (i.e |A| = log(|S|)/log2). This help us drastically cut unnecessary computation and runtime.
#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
int main () {
int n; cin>>n;
vi S, A, sums;
unordered_map<int, int> freq;
for (int i=0;i<(int) pow(2.0, n);i++) {
int a; cin>>a;
S.push_back(a);
}
sort(S.begin(), S.end());
// edge cases
A.push_back(S[1]);
if (n == 1) {for (auto v : A) cout << v << "\n"; return 0;}
A.push_back(S[2]);
if (n == 2) {for (auto v : A) cout << v << "\n"; return 0;}
sums.push_back(0); sums.push_back(S[1]); sums.push_back(S[2]);
sums.push_back(S[1] + S[2]);
freq[S[1] + S[2]]++; // IMPT: we only need frequency of composite elements
for (int i=3; i < S.size(); i++) {
if (A.size() == n) break; // IMPT: prune the search space
// has to be a new element in A
if (freq[S[i]] == 0) {
// compute the new subset sums with the addition of a new element
vi newsums = sums;
for (int j=0;j<sums.size();j++) {
int y = sums[j] + S[i];
newsums.push_back(y);
if (j != 0) freq[y]++; // IMPT: coz we only need frequency of composite elements
}
// update A and subset sums
sums = newsums;
A.push_back(S[i]);
} else {
// has to be a summation of the previous elements in A
freq[S[i]]--;
}
}
for (auto v : A) cout << v << "\n";
}

How many matrices have trace equal to givan trace?

I have given a trace 'n' of matrix.And I want to find out that how many matrices(of order 2*2 only) are there whose trace is equals to 'n' and all the matrices must be positive invertible , i.e their determinant must be greator than '0'.
For ex:
trace=3
No.of matrices=2
trace=4
No.of matrices=11
trace=5
No.of matrices=30
I have written a code for this,but it is not efficient because my code giving output successfully for n=1500,after that I'm getting time limit exceeded.
Can anyone help me?
My code is:
#include<stdio.h>
int main()
{
int t,n,nsot,i,j,l;
int arr[2000],k;
unsigned long long sum1=0,sum2=0,sum=0;
scanf("%d",&t);
while(t--)
{
sum1=0;
sum2=0;
//sum=0;
scanf("%d",&n);
nsot=n/2;
for(i=1;i<=nsot;i++)
{
arr[i]=i*(n-i);
//printf("%d ",arr[i]);
sum1=0;
for(k=1;k<arr[i];k++)
{
//printf("%f\n",ceil(arr[i]/k));
sum1=sum1+((arr[i] - 1) / k);
}
if(i==(n-i))
sum=sum1;
else
sum=0;
//printf("%d\n",sum);
//printf("%llu",sum2);
sum2=sum1+sum2;
}
printf("%llu\n",(2*sum2)-sum);
}
}
So I'm guessing you want positive matrix elements and determinant > 0.
The possible values for the trace are [1, n - 1]; [2, n - 2] ..., so n -1 values.
We will check, for each of these (O(n) checks), in how many ways we can fill in the remaining elements of the matrix such that the determinant stays positive.
Let the matrix be:
a1 a3
a4 a2
The determinant is then a1*a2 - a3*a4. For a fixed a1 and a2, iterate a3 from 1 to n - 1. You'll then have to solve:
a1*a2 - x*a4 > 0
a1*a2 > x*a4
x < a1*a2 / a4
So you can find x in O(1) => total complexity O(n^2), which should be very fast.
This seems to be what you're doing, except your innermost loop makes it O(n^3) (you also iterate x):
l=1;
while(k*l<arr[i])
{
sum1++;
l++;
}
Say k = 10 and arr[i] = 103. What will l be at the end? Can you find a relation between 10, 103 and the final value of l? That will be your formula.
Your problem is a specialization of the well known problem of integer partitioning. p(n) is the number of ways of writing n as a sum of positive integers (the order does not matter), and p(n,k) is the number of ways to write n as a sum of k integers. Your problem starts from p(n,2), and adds some extra conditions. There is a wealth of literature on integer partitioning algorithms, you should start from one of them.
However, mind that integer partitioning is NP-complete, so it's natural that it will diverge quickly as n grows.

Finding two minimum values out of four?

So, I have four integers and I need to find out the lowest two out of those four. What would be the most efficient way of doing so in C (or any other language)?
Edit: I need a fixed implementation, for the sake of efficiency as this is a very critical operation that is going to be performed thousands of times.
Here's an efficient implementation using sorting networks:
inline void Sort2(int *p0, int *p1)
{
if (*p0 > *p1)
{
const int temp = *p0;
*p0 = *p1;
*p1 = temp;
}
}
inline void Sort4(int *p0, int *p1, int *p2, int *p3)
{
Sort2(p0, p1);
Sort2(p2, p3);
Sort2(p0, p2);
Sort2(p1, p3);
Sort2(p1, p2);
}
This takes only 5 compares and up to 5 swaps. You can just ignore the results for p2, p3.
Note that for a performance-critical application Sort2 can be implemented without branches in one or two instructions on some architectures.
Just write a loop and keep track of the lowes 2 values ?
Should be at max O(2N) which is i think the best achievable complexity.
The most efficient way? Trying to avoid any extra steps, I got this (in pseudo-code). This will avoid any unnecessary comparisons that you'll get with other more general solutions (specifically ones that don't advantage of the transitive nature of comparison operations).
Bear in mind that this is only thinking about efficiency, not at all aiming for beautiful code.
if a<=b:
if b<=c:
# c too big, which of b and d is smaller?
if b<=d:
return (a,b)
else:
return (a,d)
else if b<=d:
# a and c both < b, and b < d
return (a,c)
else:
# b is > a, c and d. Down to just those three.
if a<=c:
if c<=d:
# a < c < d
return (a,c)
else:
# a and d both < c
return (a,d)
else if d<=a:
# Both c and d < a
return (c,d)
else:
# c < a < d
return (a,c)
else:
# b < a
if a<=c:
# c too big, which of a and d is smaller?
if a<=d:
return (a,b)
else:
return (b,d)
else if a<=d:
# b and c both < a, and a < d
return (b,c)
else:
# a is > b, c and d. Down to just those three.
if b<=c:
if c<=d:
# b < c < d
return (b,c)
else:
# b and d both < c
return (b,d)
else if d<=b:
# Both c and d < b
return (c,d)
else:
# c < b < d
return (b,c)
I think this has a worst case of 5 comparisons and a best case of 3 (obviously there's no way of doing it in less than 3 comparison).
You can get away with exactly 4 comparisons and maximally 4 swaps.
inline void swap(int* i, int* j) {
static int buffer;
buffer = *j;
*j = *i;
*i = buffer;
}
inline void sort2(int* a, int* s) {
if (*s < a[1])
swap(s,a+1);
if (*s < a[0]) // it is NOT sufficient to say "else if" here
swap(s,a);
}
inline void sort4(int* a) {
sort2(a,a+2);
sort2(a,a+3);
}
The result will be sitting the the first to cells, but note that these cells are not necessarily sorted! They're just the smallest elements.
I would make an array out of them, sort and take the first two values.
You can accomplish it with at most 4 comparisons:
compare the first pair of numbers and let the smaller be a1 and the larger be a2
compare the second pair of numbers and let the smaller be a3 and the larger be a4
if a1 >= a4 return (a3, a4)
(now we know that that a1 < a4)
if a3 >= a2 return (a1, a2)
(now we also know that a3 < a2)
return (a1, a3)
To see that this is true, you can check all the combinations of possible returns:
(a1, a2) (a1, a3) (a1, a4)
(a2, a3) (a2, a4)
(a3, a4)
I think you can sort the array and pick the first two elements.

get a random number when merging 2 array

I want to merge 2 arrays into 1. For example:
A1= 1,1
A2= 2,2
then A3 = 1,2,1,2
For example:
A1= 1
A2= 2,2,2,2
then A3 = 1,2,2,2,2
For example:
A1= 1,1,1,1
A2= 2,2
then A3 = 1,2,1,2,1,1
In last example, when I ran my code, I got 1,2,1,2,1,20.
In the second last, I got 1,2,32767,2,2.
So I guess I have a wrong code. Right after the I finished taking the element of the shorter array and fill up all the rest of the A3 with whoever is longer. But I couldn't figure out why — can you help me?
code:
int *p3=arr3; //arr3 is A3 for example, arr1 = A1..etc, all sizes are defined
int index;
int index1=0;
int index2=0;
for(index = 0; index< sizeofArr3 ; index++)
{
if(index%2==0)
{
if(index1<=sizeofArr1)
*(p3++) = arr1[index1++];
else
*(p3++) = arr2[index2++];
}
else
{
if(index2<=sizeofArr2)
*(p3++) = arr2[index2++];
else
*(p3++) = arr1[index1++];
}
}
It's this line:
if (index1 <= sizeofArr1)
and the equivalent one for index2 and sizeofArr2. You should be using < rather than <=.
The reason has to do with C's zero-based arrays. For an array of size N, the element indexes are 0 through N-1 inclusive. Because you're allowing it to access element N (the N+1th element), you're actually invoking undefined behaviour.
Theoretically, the implementation can do anything in that case, up to and including destruction of the universe. I guess you're lucky that it just decided to give you results that were slightly awry :-)
Should <= sizeOfArr1 and 2 actually be < sizeOfArr1 and 2? How are you calculating your sizes?
The tests in the loops should be:
if (index1 < sizeofArr1)
with < rather than <=, assuming that the sizeofArr1 is a count of the number of elements in the array, rather than the maximum valid index in the array. When the arrays are the same length, this discrepancy doesn't matter (so the first sequence was OK), but when the arrays are different lengths, it does matter.

Interleave array in constant space

Suppose we have an array
a1, a2,... , an, b1, b2, ..., bn.
The goal is to change this array to
a1, b1, a2, b2, ..., an, bn in O(n) time and in O(1) space.
In other words, we need a linear-time algorithm to modify the array in place, with no more than a constant amount of extra storage.
How can this be done?
This is the sequence and notes I worked out with pen and paper. I think it, or a variation, will hold for any larger n.
Each line represents a different step and () signifies what is being moved this step and [] is what has been moved from last step. The array itself is used as storage and two pointers (one for L and one for N) are required to determine what to move next. L means "letter line" and N is "number line" (what is moved).
A B C D 1 2 3 4
L A B C (D) 1 2 3 4 First is L, no need to move last N
N A B C (3) 1 2 [D] 4
L A B (C) 2 1 [3] D 4
N A B 1 (2) [C] 3 D 4
L A (B) 1 [2] C 3 D 4
N A (1) [B] 2 C 3 D 4
A [1] B 2 C 3 D 4 Done, no need to move A
Note the varying "pointer jumps" - the L pointer always decrements by 1 (as it can not be eaten into faster than that), but the N pointer jumps according to if it "replaced itself" (in spot, jump down two) or if it swapped something in (no jump, so the next something can get its go!).
This problem isn't as easy as it seems, but after some thought, the algorithm to accomplish this isn't too bad. You'll notice the first and last element are already in place, so we don't need to worry about them. We will keep a left index variable which represents the first item in the first half of the array that needs changed. After that we set a right index variable to the first item in the 2nd half of the array that needs changed. Now all we do is swap the item at the right index down one-by-one until it reaches the left index item. Increment the left index by 2 and the right index by 1, and repeat until the indexes overlap or the left goes past the right index (the right index will always end on the last index of the array). We increment the left index by two every time because the item at left + 1 has already naturally fallen into place.
Pseudocode
Set left index to 1
Set right index to the middle (array length / 2)
Swap the item at the right index with the item directly preceding it until it replaces the item at the left index
Increment the left index by 2
Increment the right index by 1
Repeat 3 through 5 until the left index becomes greater than or equal to the right index
Interleaving algorithm in C(#)
protected void Interleave(int[] arr)
{
int left = 1;
int right = arr.Length / 2;
int temp;
while (left < right)
{
for (int i = right; i > left; i--)
{
temp = arr[i];
arr[i] = arr[i - 1];
arr[i - 1] = temp;
}
left += 2;
right += 1;
}
}
This algorithm uses O(1) storage (with the temp variable, which could be eliminated using the addition/subtraction swap technique) I'm not very good at runtime analysis, but I believe this is still O(n) even though we're performing many swaps. Perhaps someone can further explore its runtime analysis.
First, the theory: Rearrange the elements in 'permutation cycles'. Take an element and place it at its new position, displacing the element that is currently there. Then you take that displaced element and put it in its new position. This displaces yet another element, so rinse and repeat. If the element displaced belongs to the position of the element you first started with, you have completed one cycle.
Actually, yours is a special case of the question I asked here, which was: How do you rearrange an array to any given order in O(N) time and O(1) space? In my question, the rearranged positions are described by an array of numbers, where the number at the nth position specifies the index of the element in the original array.
However, you don't have this additional array in your problem, and allocating it would take O(N) space. Fortunately, we can calculate the value of any element in this array on the fly, like this:
int rearrange_pos(int x) {
if (x % 2 == 0) return x / 2;
else return (x - 1) / 2 + n; // where n is half the size of the total array
}
I won't duplicate the rearranging algorithm itself here; it can be found in the accepted answer for my question.
Edit: As Jason has pointed out, the answer I linked to still needs to allocate an array of bools, making it O(N) space. This is because a permutation can be made up of multiple cycles. I've been trying to eliminate the need for this array for your special case, but without success.. There doesn't seem to be any usable pattern. Maybe someone else can help you here.
It's called in-place in-shuffle problem. Here is its implementation in C++ based on here.
void in_place_in_shuffle(int arr[], int length)
{
assert(arr && length>0 && !(length&1));
// shuffle to {5, 0, 6, 1, 7, 2, 8, 3, 9, 4}
int i,startPos=0;
while(startPos<length)
{
i=_LookUp(length-startPos);
_ShiftN(&arr[startPos+(i-1)/2],(length-startPos)/2,(i-1)/2);
_PerfectShuffle(&arr[startPos],i-1);
startPos+=(i-1);
}
// local swap to {0, 5, 1, 6, 2, 7, 3, 8, 4, 9}
for (int i=0; i<length; i+=2)
swap(arr[i], arr[i+1]);
}
// cycle
void _Cycle(int Data[],int Lenth,int Start)
{
int Cur_index,Temp1,Temp2;
Cur_index=(Start*2)%(Lenth+1);
Temp1=Data[Cur_index-1];
Data[Cur_index-1]=Data[Start-1];
while(Cur_index!=Start)
{
Temp2=Data[(Cur_index*2)%(Lenth+1)-1];
Data[(Cur_index*2)%(Lenth+1)-1]=Temp1;
Temp1=Temp2;
Cur_index=(Cur_index*2)%(Lenth+1);
}
}
// loop-move array
void _Reverse(int Data[],int Len)
{
int i,Temp;
for(i=0;i<Len/2;i++)
{
Temp=Data[i];
Data[i]=Data[Len-i-1];
Data[Len-i-1]=Temp;
}
}
void _ShiftN(int Data[],int Len,int N)
{
_Reverse(Data,Len-N);
_Reverse(&Data[Len-N],N);
_Reverse(Data,Len);
}
// perfect shuffle of satisfying [Lenth=3^k-1]
void _PerfectShuffle(int Data[],int Lenth)
{
int i=1;
if(Lenth==2)
{
i=Data[Lenth-1];
Data[Lenth-1]=Data[Lenth-2];
Data[Lenth-2]=i;
return;
}
while(i<Lenth)
{
_Cycle(Data,Lenth,i);
i=i*3;
}
}
// look for 3^k that nearnest to N
int _LookUp(int N)
{
int i=3;
while(i<=N+1) i*=3;
if(i>3) i=i/3;
return i;
}
Test:
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int length = sizeof(arr)/sizeof(int);
in_place_in_shuffle(arr, length);
After this, arr[] will be {0, 5, 1, 6, 2, 7, 3, 8, 4, 9}.
If you can transform the array into a linked-list first, the problem becomes trivial.

Resources