Media-of-3 partitioning in QuickSort - quicksort

I was trying to understand quicksort with median-of-3 partitioning. After finding the median of the first, middle and last element in an array, a common practice is to swap median with the second last element in array(n-1th index). Is there a specific reason we do that?

The reason is that the algorithm does not only find the median, it also sorts the low, middle and high elements. After the three permutations you know that a[middle]<=a[high]. So you need only to partition the elements before high, because a[high] is greater or equal to pivot.
Let's look at an example: low=0, middle=4 and high=8. Your array is like this:
lowerOrEqualToPivot X X X pivot X X X greaterOrEqualToPivot
If you swap middle with high, you need to partition the 8 elements between brackets :
[ lowerOrEqualToPivot X X X greaterOrEqualToPivot X X X ] pivot
If you swap middle with high-1, you need to split only 7 elements:
[ lowerOrEqualToPivot X X X X X X ] pivot greaterOrEqualToPivot
By the way there is a bug in the first line:
int middle = ( low + high ) / 2; //Wrong
int middle = ( low + high ) >>> 1; //Correct
The reason is that if (low + high) is greater than Integer.MAX_VALUE you will have an overflow and middle will be a negative number. The second line will always give you a positive result.

Related

What is the expected length of the linked list in the bucket h(x) where x is inserted?

Imagine you have a weird hash function h: with probability 1/2 it maps a key uniformly at
random to one of the array slots in the range [0,m/4−1]; with probability 1/2, it maps a key
uniformly at random to one of the array slots in the range [m/4,m−1]. (Note: this assumption
is a replacement for the simple uniform hashing assumption.)
Assume chaining is used to resolve collisions, and that n items have been previously inserted
into the hash table. If a new item x is inserted, what is the expected length of the linked list in
the bucket h(x) where x is inserted?
(n/m)
(m/n)
(1/2)(n/m)
(1/2)(m/n)
(4/3)(n/m)
(3/4)(n/m)
(3/4)(m/n)
None of the above.
The answer is: (4/3)(n/m)
Can someone explain to me how do you calculate the expected value? My probability background is pretty weak so any explanation will help. Thanks!
No. of buckets in 1st half = (m/4 - 1) - (0) + 1 = m/4.
No. of buckets in 2nd half = (m - 1) - (m/4) + 1 = 3m/4.
Half of the n items would have gone into each side.
So n/2 items in 1st half to fit into m/4 buckets; n/2 items in 2nd half to fit into 3m/4 buckets.
E(length of linked list, i.e. “repeats” in 1st half) = n/2 / m/4 = 2(n/m).
E(length of linked list, i.e. “repeats” in 2nd half) = n/2 / 3m/4 = (2/3)(n/m).
x has an equal chance of being inserted into 1st half and 2nd half,
i.e. P(x in 1st half) = 1/2, P(x in 2nd half) = 1/2.
E(length of linked list in x’s bucket) = (1/2) (2(n/m)) + (1/2) ((2/3)(n/m) = n/m + (1/3)(n/m) = (4/3)(n/m).

Formula to obtain amount to add to Starting Value so the added amount will = 5% of New Total

Is there a formula that will work in T-SQL that can obtain the following?
Solve for x where adding x to starting value, will equal 105% of starting value.
Example
Starting value of 380.
Add x to 380 so that x is 5% of total (380 + x)
In this case, x is an even 20.
This is not 5% of the Starting value, which, would be simple. I'm looking for x to equal 5% of the new value after it's been added to the starting value.
Thank you!
I'm looking for x to equal 5% of the new value after it's been added to the starting value.
Let's do some 9th grade algebra :) I'll even show my work.
If S is the starting value, we have this equation:
x = 0.05 * (S + x)
Now solve for x:
x = 0.05S + 0.05x // distribute the constant
0.95x = 0.05S // subtract the smaller x term from both sides
x = (0.05 / 0.95) * S // divide the 0.95 from both sides
x = S / 19 // multiply the right side by 1 (20/20) to simplify
So we see you can divide the starting value by 19 to get the desired x value.
And an alternative way to solve the equation, because I think this kind of thing is fun:
x = (1/20) * (S + x) // convert the decimal to a fraction
x = (S + x) / 20 // reduce/simplify the fraction multiplication
20x = S + x // multiply both sides by 20, to remove division
19x = S // subtract the smaller x term from both sides
// (hey, we solved for S along the way)
x = S / 19 // Divide both sides by 19
It's always nice when two approaches give the same solution :). This was more steps, but the steps were simpler.

calculate conservative interpolation of two vectors in matlab

G'day
Firstly, apologies for poor wording - I'm at a bit of a loss of how to describe this problem. I'm trying to calculate the conservative interpolation between two different vertical coordinate systems.
I have a vector of ocean transport values Ts, that describe the amount of transport at different depth values S. These depths are unevenly spaced (and size(S) is equal to size(Ts)+1 as the values in S are the depths at the top and bottom over which the transport value applies). I want to interpolate(/project?) this onto a vector of regularly spaced depths Z, where each new transport value Tz is formed from the values of Ts but weighted by the amount of overlap.
I've drawn a picture of what I mean (sorry for the bad quality webcam picture) I want to go from Ts1,Ts2.Ts3...TsN (bottom lines) to Tz1,Tz2,...TzN (top lines). The locations in the x direction for these are s0,s1,s2,...sN and z0,z1,z2,...zN. An example of the 'weighted overlap' would be:
Tz1 = a/(s1-s0) Ts1 + b/(s2-s1) Ts2 + c/(s3-s2) Ts3
where a, b and c are shown in the image as the length of overlap.
Some more details:
Example of z and s follow:
z = 0:5:720;
s = [222.69;...
223.74
225.67
228.53
232.39
237.35
243.56
251.17
260.41
271.5
284.73
300.42
318.9
340.54
365.69
394.69
427.78
465.11
506.62
551.98
600.54
651.2];
Note that I'm free to define z, but not s. Typically, z will be bigger than s (i.e. the smallest value in z will be smaller than in s, while the largest value in z will be larger than in s).
Help or tips greatly appreciated. Cheers,
Dave
I don't think there is an easy solution, as stated in the comments. I'll give it a go though :
One hypothesis first : We assume z0>s0 in order for your problem to be defined.
The idea (for your example) would be to get to the array below :
1 (s1-z0) s1-s0 Ts1
1 (s2-s1) s2-s1 Ts2
1 (z1-s2) s3-s2 Ts3
2 (s3-z1) s3-s2 Ts3
2 (z2-s3) s4-s3 Ts4
3 (z3-z2) s4-s3 Ts4
......
Then we would be able to compute, for each row : column1*column3/column2 and then use accumarray to sum the results with respect to the indexes in the first column.
Now the hardest part is to get this array :
Suppose you have :
A Nx1 vectors Ts
2 (N+1)x1 vectors s and z, with z(1)>s(1).
Vectsz=sort([s(2:end);z]); % Sorted vector of s and z values
In your case this vector should look like :
z0
s1
s2
z1
s3
z2
z3
...
The first column will serve as a subscript to apply accumarray, so we'll want it to increase each time there is a z value in our vector Vectsz
First=interp1(z,1:length(z),Vectsz,'previous');
Second=[diff(Vectsz);0]; % Padded with a 0 to keep the right size
Temp=diff(s);
Third=interp1(s(1:end-1),Temp,Vectsz,'previous');
This will just repeat the diff value everytime you have a z value in your vector Vectsz.
The last column is built exactly like the third one
Fourth=interp1(s(1:end-1),Ts,Vectsz,'previous');
Now that the array is built, a call to accumarray is enough to get the final result :
Res=accumarray(First,Second.*Fourth./Third);
EDIT : There is actually no need for the use of interp1 with the previous option :
Vectsz=sort([s(2:end);z]);
First=cumsum(ismember(Vectsz,z));
Second=[diff(Vectsz);0];
idx=cumsum(ismember(Vectsz,s(2:end)))+1;
Diffs=[diff(s);0];
Third=Diffs(idx);
Fourth=Ts(idx);
Res=accumarray(First,Second.*Fourth./Third);

Create an increasing integer alternating sequence in MATLAB / Octave

I'm trying to find a way to create a number pattern like the one below
0,1,-2,3,-4,5....
Please note: it needs to go to 200000, but I will be splitting them up into groups of 2000.
I found a formula that looks like it would work on http://oeis.org/A181983, but when I create the formula in MATLAB / Octave, the numbers don't match up:
f_num= #(x) x / (1 + x)^2;
numval = f_num(1)
numval = 0.25000
Is there another way I should be doing this?
Method #1 - Using (-1)^x
Just use a linear increment operator to go from 0 to 200000 and multiply the sequence by (-1)^(x+1) to allow the sign of the sequence to alternate:
x = 0:200000;
y = ((-1).^(x+1)) .* x;
The addition of the +1 is important so that the even positions get a positive sign while the odd positions get a negative sign.
Method #2 - Using indexing
Alternatively, you can declare the same array from 0 to 200000, index into every even position and negate the sign:
x = 0:200000;
x(2:2:end) = -x(2:2:end);
Method #3 - Using trigonometry and integers
One more to throw into the mix. You know that for cos(x*pi), the output is -1 when x is odd and the output is 1 when x is even. We need to flip this for your case and ultimately use this alternating sequence to multiply with the same array going from 0 to 200000, and therefore:
x = 0:200000;
y = (-cos(x*pi)).*x;
Aside
Interestingly enough, (-1)^x is also equal to exp(i*pi*x) for all values of x that are integer. We can verify this by using Euler's formula where: exp(i*pi*x) = cos(pi*x) + i*sin(pi*x). Since i*sin(pi*x) = 0 for all x belonging to an integer, we really get exp(i*pi*x) = cos(pi*x). Substituting even numbers of x will give us 1 while odd numbers of x will give us -1, and hence exp(i*pi*x) = cos(pi*x) = (-1)^x for all x belonging to integers.
Also, (-1)^(x+1) = -(-1)^x = -cos(x*pi) for all x belonging to integers and so the first method is really equal to the third method anyway!
try
f_num= #(x) x * (-1)^(x+1);

Using find on non-integer MATLAB array values

I've got a huge array of values, all or which are much smaller than 1, so using a round up/down function is useless. Is there anyway I can use/make the 'find' function on these non-integer values?
e.g.
ind=find(x,9.5201e-007)
FWIW all the values are in acceding sequential order in the array.
Much appreciated!
The syntax you're using isn't correct.
find(X,k)
returns k non-zero values, which is why k must be an integer. You want
find(x==9.5021e-007);
%# ______________<-- logical index: ones where condition is true, else zeros
%# the single-argument of find returns all non-zero elements, which happens
%# at the locations of your value of interest.
Note that this needs to be an exact representation of the floating point number, otherwise it will fail. If you need tolerance, try the following example:
tol = 1e-9; %# or some other value
val = 9.5021e-007;
find(abs(x-val)<tol);
When I want to find real numbers in some range of tolerance, I usually round them all to that level of toleranace and then do my finding, sorting, whatever.
If x is my real numbers, I do something like
xr = 0.01 * round(x/0.01);
then xr are all multiples of .01, i.e., rounded to the nearest .01. I can then do
t = find(xr=9.22)
and then x(t) will be every value of x between 9.2144444444449 and 9.225.
It sounds from your comments what you want is
`[b,m,n] = unique(x,'first');
then b will be a sorted version of the elements in x with no repeats, and
x = b(n);
So if there are 4 '1's in n, it means the value b(1) shows up in x 4 times, and its locations in x are at find(n==1).