Counting inversions which involves swaps between elements greater than a certain value - sorting

This is a homework question which I have spent quite a lot of time thinking.
Suppose I've an unsorted array of integers, and a given integer d. The task is to count the number of inversions that involves swaps greater than d.
For example, given an input array (3, 4, 3, 1) and d = 2, the number of such inversions is 1 as only the inversion between 4 and 1 is counted. The other inversions have a difference of less than 2.
Of course, an easy way to count the number of inversions is to iterate though every number of the list, and add the number of elements ahead of that number, which is smaller and the difference is more than d. However, this is a n^2 algorithm. A n \log n algorithm is needed instead.
Another more efficient algorithm is given here, where we perform mergesort on the input array and directly count from there.
https://www.geeksforgeeks.org/counting-inversions-subarrays-given-size/
However, I'm having trouble modifying this to get a correct answer.
My approach is something like this:
During the 'merge' step of mergesort, if the first item of the left subarray is smaller, then just add it to the sorted array and continue.
Else, I increment the number of inversions needed with the number of items in the left subarray greater than the first item of the right subarray by d.
Nonetheless, I'm still having trouble getting the correct answer.
Can someone please help me? Thank you.

During the merging process, if the element of index i of the left sub-array A[i] is greater than the element of index j of the right sub-array A[j], there will be j-i swaps there.
Do a binary search for the smallest element that has a difference greater than the value on the sub-array from A[i...j-1]. Then the number of swaps between elements greater than the value will be j minus the index of this smallest element.

Related

find multiple elements of different ranks from unsorted array

I am working with very interesting [problem][1]:
Given an unsorted array of n distinct elements, We want to find this set of
logn elements: those at positions 1,2,4,8,16,..., n/2 in the sorted order. (The element at position 1 in the sorted order is the minimum, the one in position 2 is the 2nd smallest, ..., and the one in position n is the largest.)
Assume n is a power of 2 . How fast can you find all these logn elements?
My thought process:
we can find elements of any rank from an array in O(n) using the median of medians. I will not find elements in the order written above which is 1,2,4,8,16,..., n/2. I will first take the middle of asked elements (say k) which is at index (logn)/2 and then i will divide original unsorted array into two parts using two parts using k and i will work on these two parts indiviually. Using this approach i am getting loglogn levels and at each level n amount of work is to be done hence time complexity is nloglogn.
But the options given link does not have this option.
[1](page 2)
https://d1b10bmlvqabco.cloudfront.net/attach/ixj45csz3f961q/grs52ylqx9y/j28yy7bo8jvm/final.pdf

Constrained Longest Increasing Subsequence

Consider an array, which has N integers. Now we are given with an index i, which can take up values from 1 through N. This particular index should always be present in the LIS that we generate. Calculate the LIS for each value at i.
How can we solve the above problem efficiently? My straightforward solution is to vary the index i for all of its values and calculate LIS. The time complexity goes up to O(N2log(N)). Can it be beaten?
Example:
N = 2. i = 1
Say the given array is [1,2].
[1,2] or [2, 2]
The longest (strictly) increasing subsequence in each case is 2 and 1.
The canonical dynamic program for LIS computes, for each k, the longest increasing subsequence of the elements at index 1..k that includes the element at index k. Using this data and the mirror image data for longest increasing subsequences of k..n, we find the LIS that includes index k as the union of the longest before k and the longest after k.
O(n log n)
Having an index i that must be in the subsequence makes it an easy task to look to the left and right and see how far you can go to remain strictly increasing. This will take at most O(N) steps.
The straight forward solution will now just repeat this for all N values at the index i, which gives a total effort of O(N^2).
But note, that when changing the value at index i, the calculations done earlier can be reused. It is only necessary to check if the the sequence can be extended beyond i in either direction or not, If yes, you know already how far (or can calculate it now once and for all).
This brings the total effort down to O(N).

How can i find the minimum interval that contains half of n numbers?

If I have n numbers , how do I find the minimum interval [a,b] that contains half of those numbers ?
Sort numbers
Set left index to 0, right to n/2-1, get difference A[right]-A[left]
Walk n/2 steps in for-loop, incrementing both indexes, calculating difference again, remember the smallest one and corresponding indexes.
Sort the numbers increasingly and compute all the differences A[i+n/2] - A[i]. The solution is given by the index that minimizes the difference.
Explanation:
There is no need to search among the intervals that contain less than n/2 numbers (because they do not satisfy the conditions) nor those that contain more elements (because if you find a suitable interval, it won't be minimal because you can remove the extreme elements).
When the elements are sorted, any sequence in the array is bounded by its first and last elements. So it suffices to sort the numbers and slide a window of n/2 elements.
Now it is more challenging to tell if this O(n log n) approach is optimal.
How about the following?
Sort the given series of numbers in ascending order.
Start a loop with i from 1st to ([n/2])th number
Calculate the difference d between i + ([n/2])th and ith number. Store the numbers i, i + [n/2] and d in an iteratable collection arr.
End loop
Find the minimum value of d from the array arr. The values of i and i + [n/2] corresponding to this d is your smallest range.

how to find one of the k smallest elements in n-k comparisions given that Array is unsorted and n is the size of the array

You are given two inputs: an integer k, and an array A containing n integers.
Give an algorithm to find any one of the k smallest elements of A, using at most
n − k comparisons. (In other words, your algorithm must return one of the k
smallest elements of A, but it doesn’t matter which one.) Explain why your
algorithm is guaranteed to find a correct answer and why it satisfies the bound
on the running time. (Hint: there is a very easy way to solve this problem).
For k=1 I can find the smallest element in n-1 comparisons - just go along the array and keep track of the smallest element seen so far.
For k=2 find the smallest element of the first n-1 elements in the array, using n-2 comparisons. This is the smallest element in the whole array unless the element you missed is smaller, in which case it is the second smallest, which is OK.
For general k, find the smallest element in the first n-k+1, neglecting the last k-1 elements in the array. The result is the smallest element unless up to k-1 of the remaining elements are smaller, in which case it is still among the k smallest elements, and you are OK.

Counting number of contiguous subarrays with positive sum in O(nlogn) using O(n) transformation

I am interested in finding the number of contiguous sub-arrays that sum to a positive value (sum>0).
More formally, Given an array of integers A[1,...,n] I am looking to count the pairs of integers (i,j) such that 1<=i<=j<=n and A[i]+...+A[j]>0.
I am familiar with Kadane's algorithm for finding the maximum sum sub-array in O(n), and using a similar approach I can count the number of these sub-arrays in O(n^2).
To do this I take the cumulative sum T(i). I then compute T(j)-T(i-1) for all j=1,...,n and i=1,...,j and just record the differences that end up positive.
Apparently though there is an O(n) time routine that transforms this problem into a problem of counting the number of inversions (which can be achieved in O(nlogn) using say merge-sort). Try as I may though, I have been unable to find this transformation.
I do understand though that somehow I must match this inversion to the fact that the sum of elements between a pair (i,j) is positive.
Does anyone have any guidance as to how to do this? Any help is greatly appreciated.
EDIT: I am actually looking for the O(n) transformation rather than an alternative (not based on transformation plus inversion counting) solution to finding the number of sub arrays.
Using the original array A, build another array sumA such that:
sumA[i] = A[0] + A[1] + ... + A[i].
Now in this sumA[] array if there are two indices i, j (i < j) such that sumA[i] < sumA[j],
Then sumA[j] - sumA[i] > 0. This is exactly the sum of all elements between indices i and j.
Hence the problem reduces to finding the number of inversions for the reverse of this array. This can be conducted by sorting the array sumA[] in descending order using mergesort and calculating the number of inversions encountered in this process.

Resources