Arrays: Find minimum number of swaps to make bitonicity of array minimum? - arrays

Suppose we are given an array of integer. All adjacent elements are guaranteed to be distinct. Let us define bitonicity of this array a as bt using the following relation:
bt_array[i] = 0, if i == 0;
= bt_array[i-1] + 1, if a[i] > a[i-1]
= bt_array[i-1] - 1, if a[i] < a[i-1]
= bt_array[i-1], if a[i] == a[i-1]
bt = last item in bt_array
We say the bitonicity of an array is minimum when its bitonicity is 0 if it has an odd number of elements, or its bitonicity is +1 or -1 if it has an even number of elements.
The problem is to design an algorithm that finds the fewest number of swaps required in order to make the bitonicity of any array minimum. The time complexity of this algorithm should be at worst O(n), n being the number of elements in the array.
For example, suppose a = {34,8,10,3,2,80,30,33,1}
Its initial bt is -2. Minimum would be 0. This can be achieved by just 1 swap, namely swapping 2 and 3. So the output should be 1.
Here are some test cases:
Test case 1: a = {34,8,10,3,2,80,30,33,1}, min swaps = 1 ( swap 2 and 3)
Test case 2: {1,2,3,4,5,6,7}: min swaps = 2 (swap 7 with 4 and 6 with 5)
Test case 3: {10,3,15,7,9,11}: min swaps = 0. bt = 1 already.
And a few more:
{2,5,7,9,5,7,1}: current bt = 2. Swap 5 and 7: minSwaps = 1
{1,7,8,9,10,13,11}: current bt = 4: Swap 1,8 : minSwaps = 1
{13,12,11,10,9,8,7,6,5,4,3,2,1}: current bt = -12: Swap (1,6),(2,5) and (3,4) : minSwaps = 3
I was asked this question in an interview, and here's what I came up with:
1. Sort the given array.
2. Reverse the array from n/2 to n-1.
3. Compare from the original array how many elements changed their position.
Return half of it.
And my bit of code that does this:
int returnMinSwaps(int[] a){
int[] a = {1,2,3,4,5,6,7};
int[] b = a;
Arrays.sort(b);
for(int i=0; i<= b.length/2 - 1; i++){
swap(b[b.length - i], b[b.length/2 - i]);
}
int minSwaps = 0;
for(int i=0;i<b.length;i++){
if(a[i] != b[i])
minSwaps++;
}
return minSwaps/2;
}
Unfortunately, I am not getting correct minimum number of ways for some test cases using this logic. Also, I am sorting the array which is making it in O(n log n) and it needs to be done in O(n).

URGENT UPDATE: T3 does not hold!
Consider α = [0, 7, 8, 3, 4, 10, 1, 6, 9, 2, 5]. There is no Sij(α) that can lower |B(α)| by more than 2.
Thinking on amendments to the method…
Warning
This solution only works when there are no array elements that are equal.
Feel free to propose generalizations by editing the answer.
Go straight to Conclusion if you want to skip the boring part.
Introduction
Let`s define the swap operator Sij over the array a:
Sij(a) : [… ai, … aj, …] → [… aj, … ai, …]   ∀i, j ∈ [0; |a|) ∩ ℤ : i ≠ j
Let`s also refer to the bitonicity as B(a), and define it more formally:
The obvious facts:
Swaps are symmetric:
Sij(a) = Sji(a)
Two swaps are independent if their target positions don`t intersect:
Sij(Skl(a)) = Skl(Sij(a))   ∀i, j, k, l : {i, j} ∩ {k, l} = ∅
Two 2-dependent swaps undo one another:
Sij(Sij(a)) = a
Two 1-dependent swaps abide to the following:
Sjk(Sij(a)) = Sij(Sik(a)) = Sik(Sjk(a))
Bitonicity difference is always even for equally sized arrays:
(B(a) – B(a')) mod 2 = 0   ∀a, a' : |a| = |a'|
Naturally, ∀i : 0 < i < |a|,
B([ai–1, ai]) – B([a'i–1, a'i]) = sgn(ai – ai–1) – sgn(a'i – a'i–1),
which can either be 1 – 1 = 0, or 1 – –1 = 2, or –1 – 1 = –2, or –1 – –1 = 0, and any number of ±2`s and 0`s summed yield an even result.
N.B.: this is only true if all elements in a differ from one another, same with a'!
Theorems
[T1]   |B(Sij(a)) – B(a)| ≤ 4   ∀a, Sij(a)
Without loss of generality, let`s assume that:
0 < i, j < |a| – 1
j – i ≥ 2
ai–1 < ai+1
aj–1 < aj+1
Depending on ai, 3 cases are possible:
ai–1 < ai < ai+1: sgn(ai – ai–1) + sgn(ai+1 – ai) = 1 + 1 = 2
ai < ai–1 < ai+1: sgn(ai – ai–1) + sgn(ai+1 – ai) = –1 + 1 = 0
ai–1 < ai+1 < ai: sgn(ai – ai–1) + sgn(ai+1 – ai) = 1 + –1 = 0
When altering ai and leaving all other elements of a intact, |B(a') – B(a)| ≤ 2 (where a' is the resulting array, for which the above 3 cases also apply), since no other terms of B(a) changed their value, except those two from the 1-neighborhood of ai.
Sij(a) implies what`s described above to happen twice, once for ai and once for aj.
Thus, |B(Sij(a)) – B(a)| ≤ 2 + 2 = 4.
Analogously, for each of the corners and j – i = 1 the max. possible delta is 2, which is ≤ 4.
Finally, this straightforwardly extrapolates to ai–1 > ai+1 and aj–1 > aj+1.
QED
[T2]   ∀a : |B(a)| ≥ 2   ∃Sij(a) : |B(Sij(a))| = |B(a)| – 2
{proof in progress, need to sleep}
[T3]   ∀a : |B(a)| ≥ 4   ∃Sij(a) : |B(Sij(a))| = |B(a)| – 4
{proof in progress, need to sleep}
Conclusion
From T1, T2 and T3, the minimal number of swaps needed to minimize |B(a)| equals:
⌊|B(a)| / 4⌋ + ß,
where ß equals 1 if |B(a)| mod 4 ≥ 2, 0 otherwise.

Related

For what cases will this logic of this code fail?

In a coding site I came across a question which seem to be very easy. But when I implement a solution it gives me wrong answers for the hidden test cases. I tried to find for what cases it failed but I just couldn't get any.
The question goes as follows
Construct an N×M matrix with entries having positive integers such that
If M>1, ith row is strictly increasing from left to right with a fixed common difference di
for all 1≤i≤N.
If N>1, jth column is strictly increasing from top to bottom with a fixed common difference cj
for all 1≤j≤M.
All the common differences should be distinct.
In the case of multiple answers, find an arrangement that minimizes the maximum element of the
matrix.
The code with the logic
#include<stdio.h>
#include<stdlib.h>
int main(){
int t=0,n=0,m=0,d=0;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
if(n>=m){
d=2;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
printf("%d ",(i+1) + j*d);
}
d+=2;
printf("\n");
}
}
else{
d=1;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
printf("%d ",(2*i+1) + j*d);
}
d+=2;
printf("\n");
}
}
}
return 0;
}
Sample input
3
3 3
1 2
1 1
Sample Output
1 2 3
3 6 9
5 10 15
1 2
1
Simple logic I tried was, check if the rows are more or the columns, whichever is more increment that by even number C.D (from 2,4,6....) and the other in odd number C.D(from 1,3,5...)
For example: for 2X3
The matrix will be
1 3
2 6
3 9
This logic seems to be correct and while discussing with my friends even they say its right. But I get wrong answers while submitting to the hidden cases.
What logic error might have I done? Could you give me a example for which this code will fail?
The matrix shown in the question for the 2×3 case is:
1 3
2 6
3 9
However, a better solution is:
1 4
2 6
3 8
We see this satisfies the constraints:
Each row and each column is strictly increasing.
Each row has a fixed difference: 3, 4, and 5.
Each column has a fixed difference: 1 and 2.
All those differences are distinct.
A general solution follows.
Let the matrix be Ai, j. It is clear A0, 0 should be 1. Let A0, 1, A1, 0, and A1, 1 be 1+a, 1+b, and 1+c, respectively. Then simple algebra and induction shows that Ai, j is 1 + (1−i)ja + i(1−j)b + ijc.
The common difference in column j is b+j(c−a−b), and the common difference is row i is a+i(c−a−b). These form two arithmetic series with the same step size, c−a−b, so they do not intersect only if they either interleave (for example, c−a−b could be 2 and one of a or b can be odd while the other is even) or one series is entirely less than the other (for example, c−a−b could be 1). We will consider these cases below.
Let I and J be the maximum subscripts in the array, m−1 and n−1, respectively. (These are introduced for brevity, as m−1 and n−1 appear repeatedly below.) The maximum element in the array, AI,J, is 1 + (1−I)Ja + I(1−J)b + IJc = 1 + IJ(c−a−b) + Ja + Ib. Observe the derivative with respect to c is positive, so, once a and b are chosen, the minimum value for AI,J is obtained by making c as small as the constraints allow, hence either c = a+b+1 (for the case when one series is entirely less than the other) or c = a+b+2 (for the case when the series interleave). For the former, AI,J = 1 + IJ + Ja + Ib. For the latter, AI,J = 1 + 2IJ + Ja + Ib. This reveals we also wish to minimize a and b subject to the constraints.
The smallest a and b can be is 1 and 2 (in either order). So in the interleaving case, we have either AI,J = 1 + 2IJ + J + 2I or AI,J = 1 + 2IJ + 2J + I. To obtain the lesser of these, we choose a = 1, b = 2 if J < I and a = 2, b = 1 otherwise. Combinging these, the maximum is 1 + 2IJ + I + J + min(I, J). Restoring m and n from I and J and doing a little algebra gives us a maximum of 2mn − max(m, n).
For the non-interleaving case, we could have a = 1, the largest row difference (generally a+i(c−a−b)) of 1+I•1 = 1+I, so b = 2+I to start the column differences (generally b+j(c−a−b)) with b + 0(c−a−b) = 2+I. Conversely, we could have b = 1 and a = 2+J. Then we have AI,J = 1+ IJ + J + I(2+I) or 1 + IJ + J(2+J) + I, or, equivalently, mn+m2−m or mn+n2−n. The former is less when m < n and vice-versa.
Note than when m ≤ n, the interleaved case gives us a maximum of 2mn − n = mn + m2 + (m−1)(n−m) − m. Since (m−1)(n−m) is non-negative, that is at least as large as mn+m2−m, which is the maximum for the non-interleaved case. The analogous result holds for n ≤ m. Therefore, the interleaved case never has any advantage. The minimum is always obtained with the non-interleaved case with either a = 1, b = 2+I = m+1 or a = 2+J = n+1, b = 1, according to which of m and n is smaller.

Maximum Sum of elements of array which is not divisible by M, deleting/avoiding at most K consequtive array elements

Given: N, K, M and A(array)
N = No. of elements in the array
K = Maximum consequtive array elements that can be avoided/not considered in the answer
|A| = N
Starting from the last index of the array, you have to find the maximum sum that can be obtained by using the elements of the array, such that at any instant the sum is not divisibe by M. The sum can be aquired by traversing from the last index to the first index of the array (in order), and you have a choice to either include that element into the final answer, or avoid it.
There are two conditions :
When an item is included, the total sum of all elements included till that moment (including the current element that is being included), should not be divisible by M.
When an item is avoided, it has to be kept in mind that you can avoid at most K consequtive array elements at once.
Note : It is strictly required to start from the last index, and skipping any index will count towards the limit on the maximum consequtive elements that can be avoided (i.e K).
If there exists no way to traverse from the last index to the first index by satisfying the two conditions at all instances of the traversal, we have to return back -1, or else return back the maximum sum possible.
Constraints :
2 <= N <= 10^5
1 <= K <= 10
1 <= M <= 20
Example 1 :
N = 5
K = 1
M = 2
A = [1, 2, 3 ,4, 5]
Output : 5 + 4 + 2 = 11
Example 2 :
N = 5
K = 2
M = 2
A = [3, 4, 2, 6, 8]
Output = -1
Example 3 :
N = 7
K = 2
M = 2
A = [1,4,2,6,3,7,7]
Output : 7 + 6 + 2 + 4 = 19
We can do 3-D dynamic programming to solve this, very similarly to the other post. Here's the definition of the formula I'm using:
Let dp[i][k][r], 0 <= i < N, 0 <= k <= K, 0 <= r < M
be the maximum valid sum achievable after processing indices [i, i+1, ..., N-1]
such that index i is our kth consecutive skip and the sum's remainder is r (mod M).
We want max(dp[0][_][_])
dp[i][k][r] = -INF if k + i > N
= -INF if r == 0 and k + i /= N
= -INF if r /= 0 and k + i == N
= 0 if r == 0 and k + i == N
= dp[i+1][k-1][r] if k > 0 and r /= 0
= A[i] + max(dp[i+1][j][(r-A[i]) % M] over all j), if k == 0
The formula is quite long, due to the fact that the initial empty sum of 0 (which is technically divisible by M) is allowed but all others are not. There's also an initial value of the formula not included above: if A[N-1] (the last element) is not divisible by M, then dp[N-1][0][A[N-1]%M] is A[N-1]. You can shorten this formula by two lines, but you do have at least 4 distinct patterns to match.
The time and space complexity are O(NMK), but the space complexity can be reduced to O(MK) by only ever storing the last two rows of your DP table.
Here's a Python computation of that DP formula:
def f(A: List[int], N: int, K: int, M: int) -> int:
assert N == len(A)
if M == 1:
return -1
dp = [[[-math.inf for _ in range(M)] for _ in range(K + 1)] for _ in range(N)]
for i in range(N):
k = N - i
if 0 <= k <= K:
dp[i][k][0] = 0
if A[N - 1] % M != 0:
dp[N - 1][0][A[N - 1] % M] = A[N - 1]
for i in reversed(range(N - 1)):
elem = A[i]
# When k == 0
for r in range(1, M):
for j in range(K + 1):
dp[i][0][r] = max(dp[i][0][r], elem + dp[i + 1][j][(r - elem) % M])
# When k > 0
for k in range(1, K + 1):
for r in range(1, M):
dp[i][k][r] = dp[i + 1][k - 1][r]
ans = max([max(x) for x in dp[0]])
return ans if math.isfinite(ans) else -1
If you'd like to test this code and other answers, plus a slow brute force solution, here's an online code-runner

Maximize sum of array after applying the given operations on the array

Given an Array A consisting of N elements and an integer K. You can perform following operations on array any number of times(Can be 0).
Choose an element from array A. Let us denote as A[i]
Choose a positive integer Y.
Change A[i] to A[i] xor Y.
The Sum of all the Y's used in the operations should not be greater than K.
Your task is to find the maximum sum of all the elements of array A after operations.
Example:-
N=5
K=6
A={9,7,7,4,3}
Output:- 36
Explanation:- In the first operation, choose the fourth element and Y=2. Then change 4 to 4 xor 2, that is 6.
the updated array will be:- 9,7,7,6,3
In second Operation, choose the fifth element and Y=4. Then change 3 to 3 xor 4, that is 7.
The updated array will be 9,7,7,6,7
Hence sum is 36.
Please someone explain the logic behind the problem. I am not getting the idea.
Since you didn't clarify my comment about Y I will assume that the answer is no, you can not count unique Y values once towards the budget K.
This problem is simply a modified 0-1 knapsack problem in disguise. To solve it using the knapsack problem:
Let the item value & weight pairs be defined as the set
I = { (Y ^ a - a, Y) : a \in A, Y \in {1,K}}
Apply the dynamic programming solution to the 0-1 knapsack problem with weight limit K, and the requirement that only one item may be picked per a \in A. The total optimal weight of the knapsack problem + any unmodified a \in A is the solution.
Here is an implementation in python that solves the example given.
#!/usr/bin/python
def solve2(w,v,W,nK):
n = len(w)
m = dict()
for j in range(0,W+1):
m[-1, j] = 0
for i in range(-1,n):
m[i, 0] = 0
for i in range(0,n):
for j in range(0,W+1):
b_w = -1
b_v = -1
found = False
for k in range(0,nK):
if w[i][k] <= j and v[i][k] >= b_v:
b_w = w[i][k]
b_v = v[i][k]
found = True
if found:
m[i, j] = max(m[i-1, j], m[i-1, j-b_w] + b_v)
else:
m[i, j] = m[i-1, j]
return m[n-1,W]
A = [9,7,7,4,3]
K = 6
v = [ [ (Y^a)-a for Y in range(1,K+1) ] for a in A]
w = [ [ Y for Y in range(1,K+1) ] for a in A]
print ('Solution value is:', sum(A) + solve2(w,v,K,K))

Number of ways to fill an array of size n , such that the mexium is greater than every element of the array?

We have given an empty array of size n , we need to fill it with natural numbers (we are allowed to repeat).
The condition that must follow is the mex of the array must be greater than all the elements we fill in the array .
Can someone pls help me with the number of ways to do so ?
(Different arrangements of same set of numbers are also considered distinct)
PS:- by mex of a sequence I mean the smallest non negative number that doesn't occur in the sequence
Number of such arrays is equivalent to the number of ordered distributions of values 1..N into buckets (so [A],[B,C] and [B,C][A] are distinct ones). And number of such distributions is described by ordered Bell numbers 1,3,13,75....
Example for N=3
1 1 1 //1 permutation
1 1 2 //3 permutations
1 2 2 //3 permutations
1 2 3 //6 permutations
//13 variants
Generation of distributions themselves for reference. Note that for N values every value might fall into part 1..K, where K is in range 1..N, so numbers of parts corresponding to all values form continuous sequence without holes (cf. your mex)
To calculate number of such distributions, we can use recurrence from Wiki, Python code:
def cnk(n, k):
k = min(k, n - k)
if k <= 0:
return 1 if k == 0 else 0
res = 1
for i in range(k):
res = res * (n - i) // (i + 1)
return res
def orderedbell(n):
a = [0]*(n+1)
a[0] = 1
for m in range(1, n+1):
for i in range(1, m+1):
a[m] += cnk(m, i) * a[m - i]
return a[n]
for i in range(1,10):
print(orderedbell(i))
1
3
13
75
541
4683
47293
545835
7087261

Difference of elements of 2 sorted arrays within given interval

Let us assume that we have 2 sorted arrays A and B of integers and a given interval [L,M] . If x is an element of A and y an element of B ,our task is to find all pairs of (x,y) that hold the following property: L<=y-x<=M.
Which is the most suitable algorithm for that purpose?
So far ,I have considered the following solution:
Brute force. Check the difference of all possible pairs of elements with a double loop .Complexity O(n^2).
A slightly different version of the previous solution is to make use of the fact that arrays are sorted by not checking the elements of A ,once difference gets out of interval .Complexity would still be O(n^2) but hopefully our program would run faster at an average case.
However ,I believe that O(n^2) is not optimal .Is there an algorithm with better complexity?
Here is a solution.
Have a pointer at the beginning of each array say i for array A and j for array B.
Calculate the difference between B[j] and A[i].
If it is less than L, increment the pointer in array B[], i.e increment j by 1
If it is more than M, increment i, i.e pointer of A.
If the difference is in between, then do the following:
search for the position of an element whose value is B[j]-A[i]-L or the nearest
element whose value is lesser than (B[j]-A[i])-L in array A. This
takes O(logN) time. Say the position is p. Increment the count of
(x,y) pairs by p-i+1
Increment only pointer j
My solution only counts the number of possible (x,y) pairs in O(NlogN) time
For A=[1,2,3] and B=[10,12,15] and L=12 and M=14, answer is 3.
Hope this helps. I leave it up to you, to implement the solution
Edit: Enumerating all the possible (x,y) pairs would take O(N^2) worst case time. We will be able to return the count of such pairs (x,y) in O(NlogN) time. Sorry for not clarifying it earlier.
Edit2: I am attaching a sample implementation of my proposed method below:
def binsearch(a, x):
low = 0
high = len(a)-1
while(low<=high):
mid = (low+high)/2
if a[mid] == x:
return mid
elif a[mid]<x:
k = mid
low = low + mid
else:
high = high - mid
return k
a = [1, 2, 3]
b = [10, 12, 15, 16]
i = 0
j = 0
lenA = len(a)
lenB = len(b)
L = 12
M = 14
count = 0
result = []
while i<lenA and j<lenB:
if b[j] - a[i] < L:
j = j + 1
elif b[j] - a[i] > M:
i = i + 1
else:
p = binsearch(a,b[j]-L)
count = count + p - i + 1
j = j + 1
print "number of (x,y) pairs: ", count
Because it's possible for every combination to be in the specified range, the worst-case is O([A][B]), which is basically O(n^2)
However, if you want the best simple algorithm, this is what I've come up with. It starts similarly to user-targaryen's algorithm, but handles overlaps in a simplistic fashion
Create three variables: x,y,Z and s (set all to 0)
Create a boolean 'success' and set to false
Calculate Z = B[y] - A[x]
if Z < L
increment y
if Z >= L and <= M
if success is false
set s = y
set success = true
increment y
store x,y
if Z > M
set y = s //this may seem inefficient with my current example
//but you'll see the necessity if you have a sorted list with duplicate values)
//you can just change the A from my example to {1,1,2,2,3} to see what I mean
set success = false
an example:
A = {1,2,3,4,5}
B = {3,4,5,6,7}
L = 2, M = 3
In this example, the first pair is x,y. The second number is s. The third pair is the values A[x] and B[y]. The fourth number is Z, the difference between A[x] and B[y]. The final value is X for not a match and O for a match
0,0 - 0 - 1,3 = 2 O
increment y
0,1 - 0 - 1,4 = 3 O
increment y
0,2 - 0 - 1,5 = 4 X
//this is the tricky part. Look closely at the changes this makes
set y to s
increment x
1,0 - 0 - 2,3 = 1 X
increment y
1,1 - 0 - 2,4 = 2 O
set s = y, set success = true
increment y
1,2 - 1 - 2,5 = 3 O
increment y
1,3 - 1 - 2,6 = 4 X
set y to s
increment x
2,1 - 1 - 3,4 = 1 X
increment y
2,2 - 1 - 3,5 = 2 O
set s = y, set success = true
increment y
2,3 - 2 - 3,6 = 3 O
... and so on

Resources