Inversions in the array, what am I getting wrong. Please have a look at the Math/Pseudo code below - arrays

I have been trying to write a pseudo code for the number of inversions.
For this illustration let our array be called mainArray of length n. and also assume that n is an even integer.
From my understanding an inversion in an array is needed when i<j, mainArray[i] > mainArray[j]. We then swap places in order to sort this.
Using the merge sort algorithm, once we reach the base case and start merging the two halves (left-half and right-half) the code looks like the following
let i = 0, j=0, k=0, inversions = 0
for k in range(0,n-1)
if left-half[i] < right-half[j]
mainArray[k] = left-half[i]
i+=1
else
mainArray[k] = right-half[j]
j+=1
//now at this point an inversion has occurred
//so from my understanding at this point there was only 1 swap? because the program
//skipped left-half[i] and proceeded to right-half[j]
// so my answer was **"Inversions = Inversions + 1"** incrementing by 1 Inversions wherever the **Else-Block is run**.
//but in the solution the correct answer is
Inversions = Inversions + {(n/2)-i}
I don't get this part? why are assuming that the right-half[j] swaps places with all the remaining elements in the left-half of the array. what key-point am I missing here?
Any help would be appreciated. Thanks.

Recall that left-half and right-half is sorted, so if i<j, left-half[i] > right-half[j] this implies left-half[i+1..n/2] > right[j] too. So we count Inversions + {(n/2)-i} to count all of the inversions, not just one.

Related

Maximum sum of two elements in an array minus the distance between them

I am trying to find the maximum sum of two elements in an array minus the distance between them.
Specifically I am trying to calculate max{ a[i]+a[j]-|i-j| }
I am currently stuck. I have obviously considered the naive approach (O(n^2)). However ,I am pretty sure there is a better ,more efficient approach (O(nlogn)) or even O(n).
Can someone please help me on how to approach the problem. I would be grateful if anyone threw some hints or a simple idea to have something to start from. Sorting the array first? Maybe using a dynamic programming approach?
Edit:
I think I have found an O(n) solution
Let's assume that our max sum comes from a[i] and a[j] , a[i] contributes to that sum with : a[i]+i . a[j] contributes to that sum with a[j]-j. (Because our sum is a[i]+a[j]-|j-i|= a[i]+a[j]+i-j. )
Approach: for convenience we compute the matrices A_plus_index=a[i]+i and A_minus_index=a[i]-i.
Then we use two helping arrays:
i) The first one has for every i ,the max value of A_plus_index array considering only the elements from 0 to i.
ii) The second has for every i, the max value of A_minus_index array considering only the elements from N to i ,where N is the length of array a.
Now we traverse the arrays once and find the max: A_plus_index[i]+ A_minus_index[i+1].
Total complexity O(n).
#JeffersonWhite your idea works and you could post it as an answer and accept it.
But I am going to improve upon your idea a little bit:
You could build only one array instead of 2, which contains the maximum of A[j] - j so far for each j from N-1 to 1.
And then traverse the array forward each time computing the max( A[i] + i + max_so_far-_reverse[i+1])
//Building the reverse array
max_so_far_reverse = array of length N
max_reverse = A[N-1]-(N-1)
max_so_far_reverse[N-1] = max_reverse
for j = N-2 to 1:
max_reverse = max(max_reverse, A[j]-j)
max_so_far_reverse[j] = max_reverse
//Computing maximum value by traversing forward
max = 0
for i = 0 to N-2:
max = max(max, A[i] + i + max_so_far_reverse[i+1])
return max

How do I iterate through matrix elements matlab

I have the task of creating a piece of matlab code that uses the sieve of Eratosthenes to find the list of prime numbers up to N. I have created a loop that finds the non primes and then finds the index value of them in the list of 2 to N. How do I get my program to take these index values element by element and set the corresponding positions in my zero matrix to one?
Also for my assignment I cannot use the in built isprime functions.
My code so far:
function [p,c] = sieve(N)
N = input('Please type an integer greater than 1: ');
a = ones(1,N); %Non-primes are set to 0
for k = 2:N
How does k:k:end work, I'm guessing it adds k until it reaches N.
Thanks
Assuming your matrix of zeros is called "numbersthatareprime" and your prime indices are called "primeindices":
numbersthatareprime(primeindices)=1
That's just a matter of using your array to index into your vector. As such, create a vector of all zeros that is N in length, then assuming you have the list of prime numbers up to N which is called prim, just do:
vec = zeros(1, N);
vec(prim) = 1;
OK
As OP may still be confused, I'll just give a new answer (not dissimilar to my previous wrong one)
x=zeros(100,1);
for i=2:100;
x(2*i:i:end)=1;
end; find(~x)
You just need to go from 2*i rather than i....
You don't really need a matrix. Just a list of values!
X=zeros(10000,1);
for i=2:100
X(i:i:end) = 1
end
Here, the indexing i:i:end means
[2,4,6,8,...] when i==2
[3,6,9,...] when i==3
etc
So it sets all the multiples of 2, then all the multiples of 3 etc., creating your seive.
Note that you only need to go up to sqrt(N).
Then you can just do find(X) to get the primes!

Number of ways such that sum of k elements equal to p

Given series of integers having relation where a number is equal to sum of previous 2 numbers and starting integer is 1
Series ->1,2,3,5,8,13,21,34,55
find the number of ways such that sum of k elements equal to p.We can use an element any number of times.
p=8
k=4.
So,number of ways would be 4.Those are,
1,1,1,5
1,1,3,3
1,2,2,3
2,2,2,2
I am able to sove this question through recursion.I sense dynamic programming here but i am not getting how to do it.Can it be done in much lesser time???
EDIT I forgot to mention that the sequence of the numbers does not matter and will be counted once. for ex=3->(1,2)and(2,1).here number of ways would be 1 only.
EDIT: Poster has changed the original problem since this was posted. My algorithm still works, but maybe can be improved upon. Original problem had n arbitrary input numbers (he has now modified it to be a Fibonacci series). To apply my algorithm to the modified post, truncate the series by taking only elements less than p (assume there are n of them).
Here's an n^(k/2) algorithm. (n is the number of elements in the series)
Use a table of length p, such that table[i] contains all combinations of k/2 elements that sum to i. For example, in the example data that you provided, table[4] contains {1,3} and {2,2}.
EDIT: If the space is prohibitive, this same algorithm can be done with an ordered linked lists, where you only store the non-empty table entries. The linked list has to be both directions: forward and backwards, which makes the final step of the algorithm cleaner.
Once this table is computed, then we get all solutions by combining every table[j] with every table[p-j], whenever both are non-empty.
To get the table, initialize the entire thing to empty. Then:
For i_1 = 0 to n-1:
For i_2 = i_1 to n-1:
...
For i_k/2 = i_k/2-1 to n-1:
sum = series[i_1] + ... + series[i_k/2]
if sum <= p:
store {i_1, i_2, ... , i_k/2 } in table[sum]
This "variable number of loops" looks impossible to implement, but actually it can be done with an array of length k/2 that keeps track of where each i_` is.
Let's go back to your data and see how our table would look:
table[2] = {1,1}
table[3] = {1,2}
table[4] = {1,3} and {2,2}
table[5] = {2,3}
table[6] = {1,5}
table[7] = {2,5}
table[8] = {3,5}
Solutions are found by combining table[2] with table[6], table[3] with table[5], and table[4] with table[4]. Thus, solutions are: {1,1,1,5} {1,2,2,3}, {1,1,3,3}, {2,2,2,2}, {1,3,2,2}.
You can use dynamic programming. Let C(p, k) be the number of ways that sum k element equal to p and a be the array of elements. Then
C(p, k) = C(p - a[0], k - 1) + C(p - a[1], k - 1) + .... + C(p - a[n-1], k - 1)
Then, you can use memorization to speed up your code.
Hint:
Your problem is well-known. It is the sum set problem, a variation of knapsack problem. Check this pretty good explanation. sum-set problem

Replace numbers on even positions in sorted array

I have an array sorted in ascended order. I want to replace the biggest m numbers found even positions in the array with 0.
My algorithm that I thought looks like this:
k=1;
for j=n:1 %%starting from last position to first
if(rem(j,2)==0 && (k<=m)) %%checking if the position is even & not getting over m numbers
B(j) = 0;
k = k + 1;
end
end
Can anyone point out why it is not working? Thank you!
A bit more complex
even = (n-rem(n,2)) : -2 : 1; % even indices in descending order
B( even(1:m) ) = 0; % set to zero
Note how n-rem(n,2) ensures that we start from the last even index into B.
PS,
It is best not to use j as a variable name in Matlab.
I believe this should do the trick. This works for vectors with both odd and even number of elements.
n = numel(B);
B((n-mod(n,2)):-2:(n-mod(n,2)-2*M)) = 0
or
n = mod(numel(B),2);
B((end-n:-2:end-n-2*M)) = 0
I prefer Shai's solution, but if your vector is huge, and M is relatively small, I would go with this approach, as it avoids creating a vector of length numel(B)/2

Need idea for solving this algorithm puzzle

I've came across some similar problems to this one in the past, and I still haven't got good idea how to solve this problem. Problem goes like this:
You are given an positive integer array with size n <= 1000 and k <= n which is the number of contiguous subarrays that you will have to split your array into. You have to output minimum m, where m = max{s[1],..., s[k]}, and s[i] is the sum of the i-th subarray. All integers in the array are between 1 and 100. Example :
Input: Output:
5 3 >> n = 5 k = 3 3
2 1 1 2 3
Splitting array into 2+1 | 1+2 | 3 will minimize the m.
My brute force idea was to make first subarray end at position i (for all possible i) and then try to split the rest of the array in k-1 subarrays in the best way possible. However, this is exponential solution and will never work.
So I'm looking for good ideas to solve it. If you have one please tell me.
Thanks for your help.
You can use dynamic programming to solve this problem, but you can actually solve with greedy and binary search on the answer. This algorithm's complexity is O(n log d), where d is the output answer. (An upper bound would be the sum of all the elements in the array.) (or O( n d ) in the size of the output bits)
The idea is to binary search on what your m would be - and then greedily move forward on the array, adding the current element to the partition unless adding the current element pushes it over the current m -- in that case you start a new partition. The current m is a success (and thus adjust your upper bound) if the numbers of partition used is less than or equal to your given input k. Otherwise, you used too many partitions, and raise your lower bound on m.
Some pseudocode:
// binary search
binary_search ( array, N, k ) {
lower = max( array ), upper = sum( array )
while lower < upper {
mid = ( lower + upper ) / 2
// if the greedy is good
if partitions( array, mid ) <= k
upper = mid
else
lower = mid
}
}
partitions( array, m ) {
count = 0
running_sum = 0
for x in array {
if running_sum + x > m
running_sum = 0
count++
running_sum += x
}
if running_sum > 0
count++
return count
}
This should be easier to come up with conceptually. Also note that because of the monotonic nature of the partitions function, you can actually skip the binary search and do a linear search, if you are sure that the output d is not too big:
for i = 0 to infinity
if partitions( array, i ) <= k
return i
Dynamic programming. Make an array
int best[k+1][n+1];
where best[i][j] is the best you can achieve splitting the first j elements of the array int i subarrays. best[1][j] is simply the sum of the first j array elements. Having row i, you calculate row i+1 as follows:
for(j = i+1; j <= n; ++j){
temp = min(best[i][i], arraysum[i+1 .. j]);
for(h = i+1; h < j; ++h){
if (min(best[i][h], arraysum[h+1 .. j]) < temp){
temp = min(best[i][h], arraysum[h+1 .. j]);
}
}
best[i+1][j] = temp;
}
best[m][n] will contain the solution. The algorithm is O(n^2*k), probably something better is possible.
Edit: a combination of the ideas of ChingPing, toto2, Coffee on Mars and rds (in the order they appear as I currently see this page).
Set A = ceiling(sum/k). This is a lower bound for the minimum. To find a good upper bound for the minimum, create a good partition by any of the mentioned methods, moving borders until you don't find any simple move that still decreases the maximum subsum. That gives you an upper bound B, not much larger than the lower bound (if it were much larger, you'd find an easy improvement by moving a border, I think).
Now proceed with ChingPing's algorithm, with the known upper bound reducing the number of possible branches. This last phase is O((B-A)*n), finding B unknown, but I guess better than O(n^2).
I have a sucky branch and bound algorithm ( please dont downvote me )
First take the sum of array and dvide by k, which gives you the best case bound for you answer i.e. the average A. Also we will keep a best solution seen so far for any branch GO ( global optimal ).Lets consider we put a divider( logical ) as a partition unit after some array element and we have to put k-1 partitions. Now we will put the partitions greedily this way,
Traverse the array elements summing them up until you see that at the next position we will exceed A, now make two branches one where you put the divider at this position and other where you put at next position, Do this recursiely and set GO = min (GO, answer for a branch ).
If at any point in any branch we have a partition greater then GO or the no of position are less then the partitions left to be put we bound. In the end you should have GO as you answer.
EDIT:
As suggested by Daniel, we could modify the divider placing strategy a little to place it until you reach sum of elements as A or the remaining positions left are less then the dividers.
This is just a sketch of an idea... I'm not sure that it works, but it's very easy (and probably fast too).
You start say by putting the separations evenly distributed (it does not actually matter how you start).
Make the sum of each subarray.
Find the subarray with the largest sum.
Look at the right and left neighbor subarrays and move the separation on the left by one if the subarray on the left has a lower sum than the one on the right (and vice-versa).
Redo for the subarray with the current largest sum.
You'll reach some situation where you'll keep bouncing the separation between the same two positions which will probably mean that you have the solution.
EDIT: see the comment by #rds. You'll have to think harder about bouncing solutions and the end condition.
My idea, which unfortunately does not work:
Split the array in N subarrays
Locate the two contiguous subarrays whose sum is the least
Merge the subarrays found in step 2 to form a new contiguous subarray
If the total number of subarrays is greater than k, iterate from step 2, else finish.
If your array has random numbers, you can hope that a partition where each subarray has n/k is a good starting point.
From there
Evaluate this candidate solution, by computing the sums
Store this candidate solution. For instance with:
an array of the indexes of every sub-arrays
the corresponding maximum of sum over sub-arrays
Reduce the size of the max sub-array: create two new candidates: one with the sub-array starting at index+1 ; one with sub-array ending at index-1
Evaluate the new candidates.
If their maximum is higher, discard
If their maximum is lower, iterate on 2, except if this candidate was already evaluated, in which case it is the solution.

Resources