Find a random number generator using a given random number generating function - algorithm

This is an interview question:
Given a function which generates a random number in [1,5],we need to use this function to generate a random number in the range [1,9].
I thought about it a lot but am not able to write an equation where ramdomness is satisfied.
People please answer.This might be helpful maybe in some future interviews.

Adapted from "Expand a random range from 1–5 to 1–7"
It assumes rand5() is a function that returns a statistically random integer in the range 1 through 5 inclusive.
int rand9()
{
int vals[5][5] = {
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 1 },
{ 2, 3, 4, 5, 6 },
{ 7, 8, 9, 0, 0 },
{ 0, 0, 0, 0, 0 }
};
int result = 0;
while (result == 0)
{
int i = rand5();
int j = rand5();
result= vals[i-1][j-1];
}
return result;
}
How does it work? Think of it like this: imagine printing out this double-dimension array on paper, tacking it up to a dart board and randomly throwing darts at it. If you hit a non-zero value, it's a statistically random value between 1 and 9, since there are an equal number of non-zero values to choose from. If you hit a zero, just keep throwing the dart until you hit a non-zero. That's what this code is doing: the i and j indexes randomly select a location on the dart board, and if we don't get a good result, we keep throwing darts.
this can run forever in the worst case, but statistically the worst case never happens. :)

int rand9()
{
int t1,t2,res = 10;
do {
t1 = rand5();
do {
t2 = rand5();
}while(t2==5);
res = t1 + 5* (t2%2);
}while(res==10);
return res;
}
now 1 to 9 has the probability of 1/9.
make some explanation:
t1 has probability of 1/5 to be 1 to 5.
t2,too.but when t2==5,discarded.so t2 has probability of 1/4 to be 1 to 4.that' to say, probability of 1/2 to be odd or even,which makes t2%2 has probability of 1/2 to be 0 to 1.
thus, t1 + 5*(t2%2) has probability of 5/10 to be 1 to 5, and 5/10 to be 6 to 10.
but 10 is discarded again,so the rest 9 numbers' probability is 1/9.

You need to use rejection sampling. That is, reject results that don't fit your target distribution. In your case you could use the lower three bits of two successive calls to your rand15 function (− 1 if necessary), concatenate them and reject those results that are outside your target interval and retry until you find a number that's inside.

Related

Need an algorithm to "evenly" iterate over all possible combinations of a set of values

sorry for the horrible title, I am really struggling to find the right words for what I am looking for.
I think what I want to do is actually quite simple, but I still can't really wrap my head around creating algorithms. I bet I could have easily found a solution on the web if I wasn't lacking basic knowledge of algorithm terminology.
Let's assume I want to iterate over all combinations of an array of five integers, where each integer is a number between zero and nine. Naturally, I could just increment from 0 to 99999. [0, 0, 0, 0, 1], [0, 0, 0, 0, 2], ... [9, 9, 9, 9, 9].
However, I need to "evenly" (don't really know how to call it) increment the individual elements. Ideally, the sequence of arrays that is produced by the algorithm should look something like this:
[0,0,0,0,0] [1,0,0,0,0] [0,1,0,0,0] [0,0,1,0,0]
[0,0,0,1,0] [0,0,0,0,1] [1,1,0,0,0] [1,0,1,0,0]
[1,0,0,1,0] [1,0,0,0,1] [1,1,0,1,0] [1,1,0,0,1]
[1,1,1,0,0] [1,1,1,1,0] [1,1,1,0,1] [1,1,1,1,1]
[2,0,0,0,0] [2,1,0,0,0] [2,0,1,0,0] [2,0,0,1,0]
[2,0,0,0,1] [2,1,1,0,0] [2,1,0,1,0] .....
I probably made a few mistake in the sequence above, but maybe you can guess what I am trying to approach. Don't introduce a number higher than 1 unless every possible combination of 0s and 1s has been determined, don't introduce a number higher than 2 unless every possible combination of 0s, 1s and 2s has been determined, and so on..
I would really appreciate someone pointing me in the right direction! Thanks a lot
You've already said that you can get the combinations you are looking for by enumerating all nk possible sequences, except that you don't get them in the desired order.
You could generate the sequences in the right order if you used an odometer-style enumerator. At first, all digits must be 0 or 1. When the odometer would wrap (after 1111...), you increment the set of the digits to [0, 1, 2]. Reset the sequence to 2000... and keep iterating, but only emit sequences that have at least one 2 in them, because you've already generated all sequences of 0's and 1's. Repeat until after wrapping you go beyond the maximum threshold.
Filtering out the duplicates that don't have the current top digit in them can be done by keeping track of the count of top numbers.
Here's an implementation in C with hard-enumed limits:
enum {
SIZE = 3,
TOP = 4
};
typedef struct Generator Generator;
struct Generator {
unsigned top; // current threshold
unsigned val[SIZE]; // sequence array
unsigned tops; // count of "top" values
};
/*
* "raw" generator backend which produces all sequences
* and keeps track of how many top numbers there are
*/
int gen_next_raw(Generator *gen)
{
int i = 0;
do {
if (gen->val[i] == gen->top) gen->tops--;
gen->val[i]++;
if (gen->val[i] == gen->top) gen->tops++;
if (gen->val[i] <= gen->top) return 1;
gen->val[i++] = 0;
} while (i < SIZE);
return 0;
}
/*
* actual generator, which filters out duplicates
* and increases the threshold if needed
*/
int gen_next(Generator *gen)
{
while (gen_next_raw(gen)) {
if (gen->tops) return 1;
}
gen->top++;
if (gen->top > TOP) return 0;
memset(gen->val, 0, sizeof(gen->val));
gen->val[0] = gen->top;
gen->tops = 1;
return 1;
}
The gen_next_raw function is the base implementation of the odometer with the addition of keeping a count of current top digits. The gen_next function uses it as backend. It filters out the duplicates and increases the threshold as needed. (All that can probably be done more efficiently.)
Generate the sequence with:
Generator gen = {0};
while (gen_next(&gen)) {
if (is_good(gen.val)) {
puts("Bingo!");
break;
}
}
You could break this down into two subproblems:
get all combinations with replacement of 0, 1, 2, ... for the given number of digits
get all (unique) permutations of those combinations
Your desired ordering is still different than the order those are typically generated in (e.g. (0,1,1) before (0,0,2), and (0,0,1) before (1,0,0)), but you can just collect all the combinations and all the permutations individually and sort them, at least requiring much less memory than for generating, collecting and sorting all those combinations.
Example in Python, using implementations of those functions from the itertools library; key=lambda c: c[::-1] sorts the lists in-order, but reversing the order of the individual elements to get your desired order:
from itertools import combinations_with_replacement, permutations
places = 3
max_digit = 3
all_combs = list(combinations_with_replacement(range(0, max_digit+1), r=places))
for comb in sorted(all_combs, key=lambda c: c[::-1]):
all_perms = set(permutations(comb))
for perm in sorted(all_perms, key=lambda c: c[::-1]):
print(perm)
And some selected output (64 elements in total)
(0, 0, 0)
(1, 0, 0)
(0, 1, 0)
...
(0, 1, 1)
(1, 1, 1)
(2, 0, 0)
(0, 2, 0)
...
(0, 1, 2)
(2, 1, 1)
...
(2, 2, 2)
(3, 0, 0)
(0, 3, 0)
...
(2, 3, 3)
(3, 3, 3)
For 27 places with values up to 27 that would still be too many combinations-with-replacement to generate and sort, so this part should be replaced with a custom algorithm.
keep track of how often each digit appears; start with all zeros
find the smallest digit that has a non-zero count, increment the count of the digit after that, and redistribute the remaining smaller counts back to the smallest digit (i.e. zero)
In Python:
def generate_combinations(places, max_digit):
# initially [places, 0, 0, ..., 0]
counts = [places] + [0] * max_digit
yield [i for i, c in enumerate(counts) for _ in range(c)]
while True:
# find lowest digit with a smaller digit with non-zero count
k = next(i for i, c in enumerate(counts) if c > 0) + 1
if k == max_digit + 1:
break
# add one more to that digit, and reset all below to start
counts[k] += 1
counts[0] = places - sum(counts[k:])
for i in range(1, k):
counts[i] = 0
yield [i for i, c in enumerate(counts) for _ in range(c)]
For the second part, we can still use a standard permutations generator, although for 27! that would be too many to collect in a set, but if you expect the result in the first few hundred combinations, you might just keep track of already seen permutations and skip those, and hope that you find the result before that set grows too large...
from itertools import permutations
for comb in generate_combinations(places=3, max_digit=3):
for p in set(permutations(comb)):
print(p)
print()

Maximum sum increasing subsequence, changing algorithm to use memoization

I have the following code which implements a recursive solution for this problem, instead of using the reference variable 'x' to store overall max, How can I or can I return the result from recursion so I don't have to use the 'x' which would help memoization?
// Test Cases:
// Input: {1, 101, 2, 3, 100, 4, 5} Output: 106
// Input: {3, 4, 5, 10} Output: 22
int sum(vector<int> seq)
{
int x = INT32_MIN;
helper(seq, seq.size(), x);
return x;
}
int helper(vector<int>& seq, int n, int& x)
{
if (n == 1) return seq[0];
int maxTillNow = seq[0];
int res = INT32_MIN;
for (int i = 1; i < n; ++i)
{
res = helper(seq, i, x);
if (seq[i - 1] < seq[n - 1] && res + seq[n - 1] > maxTillNow) maxTillNow = res + seq[n - 1];
}
x = max(x, maxTillNow);
return maxTillNow;
}
First, I don't think this implementation is correct. For this input {5, 1, 2, 3, 4} it gives 14 while the correct result is 10.
For writing a recursive solution for this problem, you don't need to pass x as a parameter, as x is the result you expect to get from the function itself. Instead, you can construct a state as the following:
Current index: this is the index you're processing at the current step.
Last taken number: This is the value of the last number you included in your result subsequence so far. This is to make sure that you pick larger numbers in the following steps to keep the result subsequence increasing.
So your function definition is something like sum(current_index, last_taken_number) = the maximum increasing sum from current_index until the end, given that you have to pick elements greater than last_taken_number to keep it an increasing subsequence, where the answer that you desire is sum(0, a small value) since it calculates the result for the whole sequence. by a small value I mean smaller than any other value in the whole sequence.
sum(current_index, last_taken_number) could be calculated recursively using smaller substates. First assume the simple cases:
N = 0, result is 0 since you don't have a sequence at all.
N = 1, the sequence contains only one number, the result is either that number or 0 in case the number is negative (I'm considering an empty subsequence as a valid subsequence, so not taking any number is a valid answer).
Now to the tricky part, when N >= 2.
Assume that N = 2. In this case you have two options:
Either ignore the first number, then the problem can be reduced to the N=1 version where that number is the last one in the sequence. In this case the result is the same as sum(1,MIN_VAL), where current_index=1 since we already processed index=0 and decided to ignore it, and MIN_VAL is the small value we mentioned above
Take the first number. Assume the its value is X. Then the result is X + sum(1, X). That means the solution includes X since you decided to include it in the sequence, plus whatever the result is from sum(1,X). Note that we're calling sum with MIN_VAL=X since we decided to take X, so the following values that we pick have to be greater than X.
Both decisions are valid. The result is whatever the maximum of these two. So we can deduce the general recurrence as the following:
sum(current_index, MIN_VAL) = max(
sum(current_index + 1, MIN_VAL) // ignore,
seq[current_index] + sum(current_index + 1, seq[current_index]) // take
).
The second decision is not always valid, so you have to make sure that the current element > MIN_VAL in order to be valid to take it.
This is a pseudo code for the idea:
sum(current_index, MIN_VAL){
if(current_index == END_OF_SEQUENCE) return 0
if( state[current_index,MIN_VAL] was calculated before ) return the perviously calculated result
decision_1 = sum(current_index + 1, MIN_VAL) // ignore case
if(sequence[current_index] > MIN_VAL) // decision_2 is valid
decision_2 = sequence[current_index] + sum(current_index + 1, sequence[current_index]) // take case
else
decision_2 = INT_MIN
result = max(decision_1, decision_2)
memorize result for the state[current_index, MIN_VAL]
return result
}

Given an array of ints and a number n, calculate the number of ways to sum to n using the ints

I saw this problem in my interview preparation.
Given an array of ints and a number n, calculate the number of ways to
sum to n using the ints
Following code is my solution. I tried to solve this by recursion. Subproblem is for each int in the array, we can either pick it or not.
public static int count(List<Integer> list, int n) {
System.out.print(list.size() + ", " + n);
System.out.println();
if (n < 0 || list.size() == 0)
return 0;
if (list.get(0) == n)
return 1;
int e = list.remove(0);
return count(list, n) + count(list, n - e);
}
I tried to use [10, 1, 2, 7, 6, 1, 5] for ints, and set n to 8. The result should be 4. However, I got 0. I tried to print what I have on each layer of stack to debug as showed in the code. Following is what I have:
7, 8
6, 8
5, 8
4, 8
3, 8
2, 8
1, 8
0, 8
0, 3
0, 7
0, 2
0, 1
0, 6
0, 7
0, -2
This result confuses me. I think it looks right from beginning to (0, 3). Starting from (0, 7), it looks wrong to me. I expect (1, 7) there. Because if I understand correctly, this is for count(list, n - e) call on second to the bottom layer on the stack. The list operation on the lower layer shouldn't impact the list on the current layer.
So my questions are:
why is it (0, 7) instead of (1, 7) based on my current code?
what adjustment should I do to my current code to get the correct result?
Thanks!
The reason why your algorithm is not working is because you are using one list that is being modified before the recursive calls.
Since the list is passed by reference, what ends up happening is that you recursively call remove until there is nothing in the list any more and then all of your recursive calls are going to return 0
What you could do is create two copies of the list on every recursive step. However, this would be way too inefficient.
A better way would be to use an index i that marks the element in the list that is being looked at during the call:
public static int count(List<Integer> list, int n, int i) {
//System.out.print(list.size() + ", " + n);
//System.out.println();
if (n < 0 || i <= 0)
return 0;
int e = list.get(i); // e is the i-th element in the list
if (e == n)
return 1 + count(list, n, i-1); // Return 1 + check for more possibilities without picking e
return count(list, n, i-1) + count(list, n - e, i-1); // Result if e is not picked + result if e is picked
}
You would then pass yourList.size() - 1 for i on the initial function call.
One more point is that when you return 1, you still have to add the number of possibilities for when your element e is not picked to be part of a sum. Otherwise, if - for example - your last element in the list was n, the recursion would end on the first step only returning 1 and not checking for more possible number combinations.
Finally, you might want to rewrite the algorithm using a dynamic approach, since that would give you a way better running time.

Maximum continuous achievable number

The problem
Definitions
Let's define a natural number N as a writable number (WN) for number set in M numeral system, if it can be written in this numeral system from members of U using each member no more than once. More strict definition of 'written': - here CONCAT means concatenation.
Let's define a natural number N as a continuous achievable number (CAN) for symbol set in M numeral system if it is a WN-number for U and M and also N-1 is a CAN-number for U and M (Another definition may be N is CAN for U and M if all 0 .. N numbers are WN for U and M). More strict:
Issue
Let we have a set of S natural numbers: (we are treating zero as a natural number) and natural number M, M>1. The problem is to find maximum CAN (MCAN) for given U and M. Given set U may contain duplicates - but each duplicate could not be used more than once, of cause (i.e. if U contains {x, y, y, z} - then each y could be used 0 or 1 time, so y could be used 0..2 times total). Also U expected to be valid in M-numeral system (i.e. can not contain symbols 8 or 9 in any member if M=8). And, of cause, members of U are numbers, not symbols for M (so 11 is valid for M=10) - otherwise the problem will be trivial.
My approach
I have in mind a simple algorithm now, which is simply checking if current number is CAN via:
Check if 0 is WN for given U and M? Go to 2: We're done, MCAN is null
Check if 1 is WN for given U and M? Go to 3: We're done, MCAN is 0
...
So, this algorithm is trying to build all this sequence. I doubt this part can be improved, but may be it can? Now, how to check if number is a WN. This is also some kind of 'substitution brute-force'. I have a realization of that for M=10 (in fact, since we're dealing with strings, any other M is not a problem) with PHP function:
//$mNumber is our N, $rgNumbers is our U
function isWriteable($mNumber, $rgNumbers)
{
if(in_array((string)$mNumber, $rgNumbers=array_map('strval', $rgNumbers), true))
{
return true;
}
for($i=1; $i<=strlen((string)$mNumber); $i++)
{
foreach($rgKeys = array_keys(array_filter($rgNumbers, function($sX) use ($mNumber, $i)
{
return $sX==substr((string)$mNumber, 0, $i);
})) as $iKey)
{
$rgTemp = $rgNumbers;
unset($rgTemp[$iKey]);
if(isWriteable(substr((string)$mNumber, $i), $rgTemp))
{
return true;
}
}
}
return false;
}
-so we're trying one piece and then check if the rest part could be written with recursion. If it can not be written, we're trying next member of U. I think this is a point which can be improved.
Specifics
As you see, an algorithm is trying to build all numbers before N and check if they are WN. But the only question is - to find MCAN, so, question is:
May be constructive algorithm is excessive here? And, if yes, what other options could be used?
Is there more quick way to determine if number is WN for given U and M? (this point may have no sense if previous point has positive answer and we'll not build and check all numbers before N).
Samples
U = {4, 1, 5, 2, 0}
M = 10
then MCAN = 2 (3 couldn't be reached)
U = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11}
M = 10
then MCAN = 21 (all before could be reached, for 22 there are no two 2 symbols total).
Hash the digit count for digits from 0 to m-1. Hash the numbers greater than m that are composed of one repeated digit.
MCAN is bound by the smallest digit for which all combinations of that digit for a given digit count cannot be constructed (e.g., X000,X00X,X0XX,XX0X,XXX0,XXXX), or (digit count - 1) in the case of zero (for example, for all combinations of four digits, combinations are needed for only three zeros; for a zero count of zero, MCAN is null). Digit counts are evaluated in ascending order.
Examples:
1. MCAN (10, {4, 1, 5, 2, 0})
3 is the smallest digit for which a digit-count of one cannot be constructed.
MCAN = 2
2. MCAN (10, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11})
2 is the smallest digit for which a digit-count of two cannot be constructed.
MCAN = 21
3. (from Alma Do Mundo's comment below) MCAN (2, {0,0,0,1,1,1})
1 is the smallest digit for which all combinations for a digit-count of four
cannot be constructed.
MCAN = 1110
4. (example from No One in Particular's answer)
MCAN (2, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1111,11111111})
1 is the smallest digit for which all combinations for a digit-count of five
cannot be constructed.
MCAN = 10101
The recursion steps I've made are:
If the digit string is available in your alphabet, mark it used and return immediately
If the digit string is of length 1, return failure
Split the string in two and try each part
This is my code:
$u = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11];
echo ncan($u), "\n"; // 21
// the functions
function satisfy($n, array $u)
{
if (!empty($u[$n])) { // step 1
--$u[$n];
return $u;
} elseif (strlen($n) == 1) { // step 2
return false;
}
// step 3
for ($i = 1; $i < strlen($n); ++$i) {
$u2 = satisfy(substr($n, 0, $i), $u);
if ($u2 && satisfy(substr($n, $i), $u2)) {
return true;
}
}
return false;
}
function is_can($n, $u)
{
return satisfy($n, $u) !== false;
}
function ncan($u)
{
$umap = array_reduce($u, function(&$result, $item) {
#$result[$item]++;
return $result;
}, []);
$i = -1;
while (is_can($i + 1, $umap)) {
++$i;
}
return $i;
}
Here is another approach:
1) Order the set U with regards to the usual numerical ordering for base M.
2) If there is a symbol between 0 and (M-1) which is missing, then that is the first number which is NOT MCAN.
3) Find the fist symbol which has the least number of entries in the set U. From this we have an upper bound on the first number which is NOT MCAN. That number would be {xxxx} N times. For example, if M = 4 and U = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3}, then the number 333 is not MCAN. This gives us our upper bound.
4) So, if the first element of the set U which has the small number of occurences is x and it has C occurences, then we can clearly represent any number with C digits. (Since every element has at least C entries).
5) Now we ask if there is any number less than (C+1)x which can't be MCAN? Well, any (C+1) digit number can have either (C+1) of the same symbol or only at most (C) of the same symbol. Since x is minimal from step 3, (C+1)y for y < x can be done and (C)a + b can be done for any distinct a, b since they have (C) copies at least.
The above method works for set elements of only 1 symbol. However, we now see that it becomes more complex if multi-symbol elements are allowed. Consider the following case:
U = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1111,11111111}
Define c(A,B) = the number of 'A' symbols of 'B' length.
So for our example, c(0,1) = 15, c(0,2) = 0, c(0,3) = 0, c(0,4) = 0, ...
c(1,1) = 3, c(1,2) = 0, c(1,3) = 0, c(1,4) = 1, c(0,5) = 0, ..., c(1,8) = 1
The maximal 0 string we can't do is 16. The maximal 1 string we can't do is also 16.
1 = 1
11 = 1+1
111 = 1+1+1
1111 = 1111
11111 = 1+1111
111111 = 1+1+1111
1111111 = 1+1+1+1111
11111111 = 11111111
111111111 = 1+11111111
1111111111 = 1+1+11111111
11111111111 = 1+1+1+11111111
111111111111 = 1111+11111111
1111111111111 = 1+1111+11111111
11111111111111 = 1+1+1111+11111111
111111111111111 = 1+1+1+1111+11111111
But can we make the string 11111101111? We can't because the last 1 string (1111) needs the only set of 1's with the 4 in a row. Once we take that, we can't make the first 1 string (111111) because we only have an 8 (which is too big) or 3 1-lengths which are too small.
So for multi-symbols, we need another approach.
We know from sorting and ordering our strings what is the minimum length we can't do for a given symbol. (In the example above, it would be 16 zeros or 16 ones.) So this is our upper bound for an answer.
What we have to do now is start a 1 and count up in base M. For each number we write it in base M and then determine if we can make it from our set U. We do this by using the same approach used in the coin change problem: dynamic programming. (See for example http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/ for the algorithm.) The only difference is that in our case we only have finite number of each elements, not an infinite supply.
Instead of subtracting the amount we are using like in the coin change problem, we strip the matching symbol off of the front of the string we are trying to match. (This is the opposite of our addition - concatenation.)

How to analyze of the complexity of this code?

I am solving a problem from codeforces. According to the editorial, the complexity of the following code should be O(n).
for(int i = n - 1; i >= 0; --i) {
r[i] = i + 1;
while (r[i] < n && height[i] > height[r[i]])
r[i] = r[r[i]];
if (r[i] < n && height[i] == height[r[i]])
r[i] = r[r[i]];
}
Here, height[i] is the height of i-th hill and r[i] is the position of the first right hill which is higher than height[i], and height[0] is the always greatest among other values of height array.
My question is, how we can guarantee the complexity of the code to be O(n) although the inner while loop's being?
In the inner while loop, the code updates r[i] values until height[i] > height[r[i]]. and the number of the updates depends on height array. For example, the number of updates of the height array sorted by non-decreasing order will be different from that of the height array sorted by non-increasing order. (in both cases, the we will sort the array except height[0], because height[0] should be always maximum in this problem).
And Is there any method to analyze an algorithm which varies on input data like this? amortized analysis will be one of answers?
PS. I would like to clarify my question more, We are to set the array r[] in the loop. And what about this? if the array height = {5,4,1,2,3} and i=1, (r[2]=3, r[3]=4 because 2 is the first value which is greater than 1, and 3 is the first value which is greater than 2) we are to compare 4 with 1, and because 4>1, we keep trying to compare 4 and 2(=height[r[2]]), 4 with 3(=height[r[3]]). In this case we have to compare 4 times to set r[1]. The number of comparison is differ from when height = {5,1,2,3,4}. Can we still guarantee the complexity of the code to be O(n)? If I miss something, Please let me know. Thank you.
I tried the mentioned algorithm with simple example, but it seems nothing changed, did I miss something ?
Example:
n = 5
height = { 2, 4, 6, 8, 10 }
r = { 1, 2, 3, 4, 5 }
---- i:4 ----
r[4] < 5 ?
---- i:3 ----
8 > 10 ?
8 = 10 ?
---- i:2 ----
6 > 8 ?
6 = 8 ?
---- i:1 ----
4 > 6 ?
4 = 6 ?
---- i:0 ----
2 > 4 ?
2 = 4 ?
-------------
height = { 2, 4, 6, 8, 10 }
r = { 1, 2, 3, 4, 5 }
Your algo (I do not know whether it will solve your problem) is actually O(n), even though there is an inner loop, but in most of the cases inner loop will not execute because of given the conditions. So in worst case it will run like 2n time, which is O(n).
You can test this assumption with a method like this where yourMethod will return the number of time it's inner loop were executed:
int arr[] = {1, 2, 3, 4, 5};
do {
int count = yourMethod(arr, 5);
}while(next_permutation(arr, arr+5));
With this you will be able check the worst case, average case, etc.

Resources