Which is the best algorithm to find sum of all subarray? - c++

for example if
a[3]={1,2,3}
1,2,3,1+2,2+3,1+2+3
so my program should print
1
2
3
3
5
8
I know there exits a formula for calculating the total sum.
But what i want is efficient method to calculate individual sums.
A seg tree advisable?

Assuming that by subarray you mean what some authors conventionally call subarray being a contiguous slice of an array, you are looking for Kadane's algorithm.
It works by incrementally finding the biggest subarray. At any given point of the search, the maximum subarray on that index is either the empty array (sum == zero) or consists of one more element than the maximum subarray that ended at the previous position. You keep track of what is the best you've ever found so you can compare subarrays with the best so far and return the actual best solution.
It may also be extended to multiple dimensions.

Related

Fast generation of random derangements

I am looking to generate derangements uniformly at random. In other words: shuffle a vector so that no element stays in its original place.
Requirements:
uniform sampling (each derangement is generated with equal probability)
a practical implementation is faster than the rejection method (i.e. keep generating random permutations until we find a derangement)
None of the answers I found so far are satisfactory in that they either don't sample uniformly (or fail to prove uniformity) or do not make a practical comparison with the rejection method. About 1/e = 37% of permutations are derangements, which gives a clue about what performance one might expect at best relative to the rejection method.
The only reference I found which makes a practical comparison is in this thesis which benchmarks 7.76 s for their proposed algorithm vs 8.25 s for the rejection method (see page 73). That's a speedup by a factor of only 1.06. I am wondering if something significantly better (> 1.5) is possible.
I could implement and verify various algorithms proposed in papers, and benchmark them. Doing this correctly would take quite a bit of time. I am hoping that someone has done it, and can give me a reference.
Here is an idea for an algorithm that may work for you. Generate the derangement in cycle notation. So (1 2) (3 4 5) represents the derangement 2 1 4 5 3. (That is (1 2) is a cycle and so is (3 4 5).)
Put the first element in the first place (in cycle notation you can always do this) and take a random permutation of the rest. Now we just need to find out where the parentheses go for the cycle lengths.
As https://mathoverflow.net/questions/130457/the-distribution-of-cycle-length-in-random-derangement notes, in a permutation, a random cycle is uniformly distributed in length. They are not randomly distributed in derangements. But the number of derangements of length m is m!/e rounded up for even m and down for odd m. So what we can do is pick a length uniformly distributed in the range 2..n and accept it with the probability that the remaining elements would, proceeding randomly, be a derangement. This cycle length will be correctly distributed. And then once we have the first cycle length, we repeat for the next until we are done.
The procedure done the way I described is simpler to implement but mathematically equivalent to taking a random derangement (by rejection), and writing down the first cycle only. Then repeating. It is therefore possible to prove that this produces all derangements with equal probability.
With this approach done naively, we will be taking an average of 3 rolls before accepting a length. However we then cut the problem in half on average. So the number of random numbers we need to generate for placing the parentheses is O(log(n)). Compared with the O(n) random numbers for constructing the permutation, this is a rounding error. However it can be optimized by noting that the highest probability for accepting is 0.5. So if we accept with twice the probability of randomly getting a derangement if we proceeded, our ratios will still be correct and we get rid of most of our rejections of cycle lengths.
If most of the time is spent in the random number generator, for large n this should run at approximately 3x the rate of the rejection method. In practice it won't be as good because switching from one representation to another is not actually free. But you should get speedups of the order of magnitude that you wanted.
this is just an idea but i think it can produce a uniformly distributed derangements.
but you need a helper buffer with max of around N/2 elements where N is the size of the items to be arranged.
first is to choose a random(1,N) position for value 1.
note: 1 to N instead of 0 to N-1 for simplicity.
then for value 2, position will be random(1,N-1) if 1 fall on position 2 and random(1,N-2) otherwise.
the algo will walk the list and count only the not-yet-used position until it reach the chosen random position for value 2, of course the position 2 will be skipped.
for value 3 the algo will check if position 3 is already used. if used, pos3 = random(1,N-2), if not, pos3 = random(1,N-3)
again, the algo will walk the list and count only the not-yet-used position until reach the count=pos3. and then position the value 3 there.
this will goes for the next values until totally placed all the values in positions.
and that will generate a uniform probability derangements.
the optimization will be focused on how the algo will reach pos# fast.
instead of walking the list to count the not-yet-used positions, the algo can used a somewhat heap like searching for the positions not yet used instead of counting and checking positions 1 by 1. or any other methods aside from heap-like searching. this is a separate problem to be solved: how to reached an unused item given it's position-count in a list of unused-items.
I'm curious ... and mathematically uninformed. So I ask innocently, why wouldn't a "simple shuffle" be sufficient?
for i from array_size downto 1: # assume zero-based arrays
j = random(0,i-1)
swap_elements(i,j)
Since the random function will never produce a value equal to i it will never leave an element where it started. Every element will be moved "somewhere else."
Let d(n) be the number of derangements of an array A of length n.
d(n) = (n-1) * (d(n-1) + d(n-2))
The d(n) arrangements are achieved by:
1. First, swapping A[0] with one of the remaining n-1 elements
2. Next, either deranging all n-1 remaning elements, or deranging
the n-2 remaining that excludes the index
that received A[0] from the initial matrix.
How can we generate a derangement uniformly at random?
1. Perform the swap of step 1 above.
2. Randomly decide which path we're taking in step 2,
with probability d(n-1)/(d(n-1)+d(n-2)) of deranging all remaining elements.
3. Recurse down to derangements of size 2-3 which are both precomputed.
Wikipedia has d(n) = floor(n!/e + 0.5) (exactly). You can use this to calculate the probability of step 2 exactly in constant time for small n. For larger n the factorial can be slow, but all you need is the ratio. It's approximately (n-1)/n. You can live with the approximation, or precompute and store the ratios up to the max n you're considering.
Note that (n-1)/n converges very quickly.

What is the cheapest way to sort a permutation in C++?

The problem is:
You have to sort an array in ascending order(permutation: numbers from 1 to N in a random order) using series of swaps. Every swap has a price and there are 5 types of prices. Write a program that sorts the given array for the smallest price.
There are two kinds of prices: priceByValue and priceByIndex. All of the prices of a kind are given in 2 two-dimensional arrays N*N. Example how to access prices:
You want to swap the 2nd and the 5th elements from the permutation with values of 4 and 7. The price for this swap will be priceByValue[4][7] + priceByIndex[2][5].
Indexes of all arrays are counted from 1 (, not from 0) in order to have access to all of the prices (the permutation elements’ values start from 1): priceByIndex[2][5] would actually be priceByIndex[1][4] in code. Moreover, the order of the indexes by which you access prices from the two-dimensional arrays doesn’t matter: priceByIndex[i][j] = priceByIndex[j][i] and priceByIndex[i][i] is always equal to 0. (priceByValue is the same)
Types of prices:
Price[i][j] = 0;
Price[i][j] = random number between 1 and 4*N;
Price[i][j] = |i-j|*6;
Price[i][j] = sqrt(|i-j|) *sqrt(N)*15/4;
Price[i][j] = max(i,j)*3;
When you access prices by index i and j are the indexes of the elements you want to swap from the original array; when you access prices by value i and j are the values of the elements you want to swap from the original array. (And they are always counted from 1)
Things given:
N - an integer from 1 to 400, Mixed array, Type of priceByIndex, priceByIndex matrix, Type of priceByValue, priceByValue matrix. (all elements of a matrix are from the given type)
Things that should 'appear on the screen': number of swaps, all swaps (only by index - 2 5 means that you have swapped 2nd and 3rd elements) and the price.
As I am still learning C++, I was wondering what is the most effective way to sort the array in order to try to find the sort with the smallest cost.
There might be a way how to access series of swaps that result a sorted array and see which one is with the smallest price and I need to sort the array by swapping the elements which are close by both value and index, but I don’t know how to do this. I would be very grateful if someone can give me a solution how to find the cheapest sort in code. Thank you in advance!
More: this problem might have no solution, I am just trying to get a result close to the ideal.
Dynamic Programming!
Think of the problem as a graph. Each of the N-factorial permutations represents a graph vertex, and the allowed swaps are just arcs between vertices. The price-tag of a swap is just the weight on the arc.
When you look at the problem this way, it can be easily solved with Dijkstra's algortihm for finding the lowest cost path through a graph from one vertex to another.
This is also called Single Pair Shortest Path
you can use an algorithm for sorting an array in lexicographical order and modify it so that it fits your needs ( you did not mention the sorting criteria like the desired result i.e. least value first, ... ) there are multiple algorithms available for this, i.e. quick sort,...
a code example is in https://www.geeksforgeeks.org/lexicographic-permutations-of-string/

finding the average number of comparisons

I would like to write an algorithm to find min and max of 100000 arrays 100000 with the size of 1000, containing random numbers from 1 to 1000. This algorithm suppose to return the average number of comparisons.
Suppose I use a naive solution with the complexity of O(n) , what does the average number of comparisons suppose to be? 1999 or 2000 (to min and max)?
I also would like to ask how to creat a random array in cpp.
You have to compare every element twice (once to the current min, once to the current max).
That's not "naive", it's the optimal way to find min and max of unsorted numbers.
There is a big difference between naive and simple / optimal ,it's always good to look for other solutions , but not always you are going to find a better or more optimal one .
as for your question you have to compare them twice once as a min and once as a max
Well, I disagree with the Sid's answer as checking each element with max and min is optimal.
Firstly, you can take first two elements and compare them together and set one as min and another as maximum.
Then you can easily in loop take 2 elements at once, compare them together and check lower one with the minimum and bigger one with the maximum.
Therefore on 2 elements you have only 3 comparisons.
It is better than checking each number with minimum and maximum, because you have 4 comparisons on 2 elements.

Find the number of ways to partition the array

I want number of ways to divide an array of possitive integers such that maximum value of left part of array is greater than or equal to the maximum value of right part of the array.
For example,
6 4 1 2 1 can be divide into:
[[6,4,1,2,1]] [[6][4,1,2,1]] [[6,4][1,2,1]] [[6,4,1][2,1]] [[6,4,1,2][1]] [[6][4,1][2,1]] [[6][4][1,2,1]] [[6][4][1,2][1]] [[6][4,1,2][1]] [[6,4,1][2][1]] [[6][4,1][2][1]] [[6,4][1,2][1]]
which are total 12 ways of partitioning.
I tried a recursive approach but it fails beacause of termination due to exceed of time limit. Also this approach is not giving correct output always.
In this another approach, I took the array ,sort it in decreasing order and then for each element I checked weather it lies on right of the original array, and if does then added it's partitions to it's previous numbers too.
I want an approach to solve this, any implementation or pseudocode or just an idea to do this would be appreciable.
I designed a simple recursive algorithm. I will try to explain on your example;
First, check if [6] is a possible/valid part of a partition.
It is a valid partition because maximum element of ([6]) is bigger than remaining part's ([4,1,2,1]) maximum value.
Since it is a valid partition, we can use recursive part of the algorithm.
concatenate([6],algorithm([4,1,2,1]))
now the partitions
[[6][4,1,2,1]], [[6][4,1][2,1]], [[6][4,1][2,1]] [[6][4][1,2,1]] [[6][4][1,2][1]] [[6][4,1,2][1]]
are in our current solution set.
Check if [6,4] is a possible/valid part of a partition.
Continue like this until reaching [6,4,1,2,1].

Maximum contiguous subsequence -- dynamic programming or greedy algorithm?

Given an array vector<int> arr with positive and negative entries, the maximum contiguous subsequence problem requires to find a (contiguous) segment of the array arr with maximum sum. Sum of empty segment is zero. The C++ code of the algorithm I'm using is as follows:
int MaxContSum(const vector<int>& arr){
int i,sum=0,max=0;
for(i=0;i<arr.size();i++){
if(arr[i]>=0) {if(sum<0) sum=0;}
else {if(sum>max) max=sum;}
sum+=arr[i];
}
if(sum>max) max=sum; return max;
}
Is this algorithm a greedy algorithm or dynamic programming? It looks like it's just scanning the entries one by one and applying different strategies based on whether arr[i] is potive or negative, a locally checkable condition. Why does this problem appear in the dynamic programming chapter, then?
This is Kadane's algorithm for the maximum subarray problem. It scans through the sequence and keeps track of the maximum subarray sum found up to this iteration in general, and the maximum subarray sum ending exactly at this point. How does it know the starting position of the subarray leading to the best sum up to exactly this point? Whenever 1) the previous sum is negative, and 2) a positive element is encountered, it pays to start at the positive element and continue from there. The proof that it works is by simple induction.
This algorithm is not greedy, but it can be viewed as dynamic programming.
A greedy algorithm makes a locally-optimum guess, and sticks with it (just continuing it further and further). Here, conversely, the algorithm can guess to check a subsequence starting at some point (where the sum ending at a positive element is negative), and later discard it and try a subsequence starting at some other point (again, because the sum becomes negative and the element is positive).
Conversely, it can be viewed as a dynamic programming problem. As the Wikipedia entry puts it:
Because of the way this algorithm uses optimal substructures (the maximum subarray ending at each position is calculated in a simple way from a related but smaller and overlapping subproblem: the maximum subarray ending at the previous position) this algorithm can be viewed as a simple example of dynamic programming.
Two main properties that problem should have in order to be eligible for solving with DP are:
Overlapping subproblems
Optimal substructure
From what you presented, first property is definitely missing and therefore I wouldn't classify this algorithm as DP. On the other hand, you use the result of the calculation for the smaller problem to get a final result - so we have Optimal substructure and that is probably the reason why you found this algorithm in the dynamic programming chapter, even though it should not belong there.