Count maximum inversions for k subarrays - arrays

I have this problem:
Given an array A and an integer K, partition A into K contiguous subarrays in the way that maximizes the sum of the number of inversions in each subarray. (An "inversion" is a pair of indices i, j where i < j and A[i] > A[j].)
Return the sum.
For example, if A = 9 1 7 2 3 and K = 2, then the answer is 4, because you can split the array into 9 1 7 2 (which has four inversions) and 3 (which has none), and 4 + 0 = 4.
Constaints
1 <= A.size <= 500
1 <= k <= A.size
1 <= A[i] <= 100000
My thoughts:
This looks like a dynamic programming problem but I can't work out how to integrate K groups into the solution.
This problems roughly translates to finding K groups with each group having the highest number of increasing elements within that group.
Any ideas on how to solve this would be helpful.

We can at least have an O(n^2 * k) dynamic program. Let f(i, k) represent the most inversions up to index i with k groups. Then:
f(i, k) = max(
inversion_count(j, i) + f(j - 1, k - 1)
)
for k <= j <= i
We can precalculate a step to make the result for inversion_count(interval) O(1) time by using O(n^2) time and space: for all elements, e, in A, store how many smaller elements are in each interval that starts at e. When we decrease j in the main iteration, increasing the size of the interval, the number of inversions increases by the number of elements smaller than A[j] in the interval [j, i], which we've precalculated.

Related

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

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

What is the maximum number of inversion an Array A of size n can have?

We have an array A[1...n]. In inversion is when i < j but A[i] > A[j].
I want a way to describe the maximum number of inversion that an array A of length n can have (consider that the starting index is 1 not 0).
I tried to find a pattern but can't seem to come up with a generalized formula for n.
at n=3 we have 3 possible inversions
at n=4 we have 7 possible inversions
at n=5 we have 10 possible inversions
at n=6 we have 15 possible inversions (10 + 5)
at n=7 we have 21 possible inversions (15 + 6)
at n=8 we have 28 possible inversions (21 + 7)
There seems to be a recurrence nb inversions for n = nb inversion for n-1 + (n-1) but it does not seem to hold for n=3,4,5.
Maximum number of inversions is reached for array sorted in reversed order.
Such array contains
(n-1) + (n-2) + (n-3) +.. + 1 = n*(n-1)/2
inversions (formula for arithmetic progression, so-called triangular numbers)
Note that at n=4 we have 7 is mistake - only 6.

Pick m numbers from array of n numbers so their total differences are minimum

There are n towers with variable number of floors in an ancient city. We have to build floors on them so that at least m out of n towers (n>=m) are of equal height. Write a function to calculate the minimum number of floors that need to be built for m floors to be of equal height.
Example: Given an array (1,5,4,2,1) each element representing the number of floors in that tower and m=3, the function should return 2 as we have to build 1 floor each to towers on index 0 & 4 so 3 towers will be of equal height. Function definition below
public Integer calcMinFloors(Integer[] towers, int m);
Updating the answer from #gnasher729:
Straightforward solution for n element array:
Sort in descending order: (5,4,2,1,1)
Loop over elements and for each element look ahead m-1 next elements. Sum the differences and save the minimum. Time complexity O(n*m)
Slightly more advanced solution:
Sort in descending order: (5,4,2,1,1)
Get first element (5), look ahead m-1 elements (4,2), count how many floors you need (1 + 3 = 4)and save the result as best and as current
Loop over array from element 2. for each element i calculate the value: current = current - (arr[i-1] - arr[i])*(m-1) + arr[i]-arr[i+m-1]. Save to best if it's smaller than it.
That should give time complexity O(n*log(n)) for sorting + O(n) for steps 2-3.
This problem is solvable is time O(NlogN) and constant space O(1), where N is the number of towers.
We have to make m towers of equal height such that we have to build minimum floors.
Important Observations
1. Because we are building minimum floors,rather than building floors on m towers and reach equal height, we will try to make m - 1 towers to be of equal height of a target tower.
2. The optimal solution lies in finding such m towers which have the minimum sum of heights difference.Let the solution be towers having following floors in ascending order:
m1 , m2 , m3 , ....... m floor
The optimal solution has the following property:
The sum of the differences is minimum:
(m - m1) + (m - m2) + (m - m3) + .....(m - (m-1))
Because only then we can say that we need to build minimum number of floors.
So it turns out we need to find set of m floors such that the difference of their heights from the floor with maximum height(within those m towers) is minimum.
Say we have array arr of length n, depicting the number of floors on each tower.First we sort the towers by their height.
Then we start finding the sum of the differences in following way.Say we are at index i in . We find the following sum:
arr[i + m - 1] - arr[i]
+
arr[i + m - 2] - arr[i]
+
arr[i + m - 3] - arr[i]
+
arr[i + m - 4] - arr[i]
.
.
.
arr[i + 1] - arr[i]
Lets call the sum s1. Now when we consider the next set of m towers , meaning towers from indices i + 1 to i + m, we do not need a loop to compute the sum of differences, it can simply be derived from following:
(m - 1)*arr[i + m] - s1 - ((m-1)*arr[i])
So using this simple mathematical technique, we only need a single for loop for this problem.
The pseudocode for the proposed algorithm is:
Sort the array arr of n towers.
Compute the sum of differences for first set of m towers.
sum = 0
for(i = 1 to m - 1)
{
sum = sum + arr[i] - arr[0]
}
Now for the remaining set of m towers
previous_sum = sum, sum = 0, j = 1
minimum_sum = previous_sum
for(i = m to n - 1)
{
sum = (m-1)*arr[i] - previous_sum - (m - 1)*arr[j - 1]
increment j
if( sum < minimum_sum )
{
minimum_sum = sum
}
previous_sum = sum
}
The answer is minimum_sum.
You sort by height in ascending or descending order, and the rest is trivial.

Optimal way to check for number of triplets where a[k]<a[i]<a[j] for all i<j<k in an array

I'm solving a problem where I have to find number of triplets of Ai, Aj, and Ak such that Ak < Ai < Aj and i < j < k in an array .
The solution to this by brute force is trivial but has complexity O(N^3). What is the optimal way to solve this?
This is an O(n^2) approach that fixes i and iterates over the rest of the array in reverse order, keeping track of the number of elements below a[i].
def count_triplets(a):
"""Count the number of triplets a[k]<a[i]<a[j] for i<j<k"""
t = 0
for i,ai in enumerate(a):
kcount = 0 # The number of elements smaller than a[i]
for x in a[:i:-1]:
if x<ai:
kcount += 1
elif x>ai:
t += kcount
return t
A=[1,6,3,4,7,4]
print count_triplets(A)
Worked example
For the given array array the interesting case is when i is equal to 1 and ai is equal to 6.
The program now works backwards over the remaining entries in the array as follows:
x = 4
x < ai so kcount increased to 1
x = 7
x > ai so t increased by kcount, i.e. t increased to 1
x = 4
x < ai so kcount increased to 2
x = 3
x < ai so kcount increased to 3
All other values of i don't end up increasing t at all, so the final value for t is 1.
TEST CODE
The Hackerrank site wants the code to support a number of inputs. The code below passes all tests.
N=input()
for n in range(N):
A=map(int,raw_input().split())
print count_triplets(A)

Resources