Can someone help with big O notation? - algorithm

void printScientificNotation(double value, int powerOfTen)
{
if (value >= 1.0 && value < 10.0)
{
System.out.println(value + " x 10^" + powerOfTen);
}
else if (value < 1.0)
{
printScientificNotation(value * 10, powerOfTen - 1);
}
else // value >= 10.0
{
printScientificNotation(value / 10, powerOfTen + 1);
}
}
assuming that imputs will not lead to infinite loops
I understand how the method goes but I cannot figure out a way to represent the method.
For example, if value was 0.00000009 or 9e-8, the method will call on printScientificNotation(value * 10, powerOfTen - 1); eight times and System.out.println(value + " x 10^" + powerOfTen); once.
So the it is called recursively by the exponent for e. But how do I represent this by big O notation?
Thanks!

Is this a trick question? That code will recurse infinitely for some of its inputs (for example, value=-1.0, powerOfTen=0), therefore its runtime is not O(f(n)) for any finite function f(n).
Edit: Assuming value > 0.0...
The run time (or recursion depth, if you prefer to look at it that way) does not depend on the value of powerOfTen, only on value. For an intial input value in the range [1.0, 10.0), the run time is constant, so O(1), For value in [10.0, +infinity), you divide value by 10 for each recursive call until value < 10.0, so the runtime is O(log10(value)). A similar argument can be made for value in the range (0.0,1.0), but note that log10 value is negative for this case. So your final answer might involve an absolute value operation. Then you might consider whether it's necessary to specify the logarithm base in the context of an asymptotic complexity analysis. Hopefully you can take it from there!

Related

Number of sigfigs to make difference significant

I am looking for an algorithm for the following (which may not be entirely well-formed, it's not yet clear in my head):
Let n1 and n2 be two double-precision floating point values. What is the smallest number of sigfigs (base 10) such that the difference n1 - n2 is significant relative to n1 and n2?
I suspect this has a well known solution but I have no background in significance arithmetic. Nevertheless here's my attempt:
If the result is significant for the larger (in magnitude) value, it is also significant for the smaller; so we can just use the larger value. Call it n.
Compute the most significant place value via floor(log10(n)). For example for the value 123.45 this would be 3, the hundreds place. Do the same for the delta.
The answer is the difference in these place values, plus 1; but never less than 1.
For example, consider 5000 - 4990. Here the difference is 10, which is significant if 5000 has three or more sigfigs. 5000 has place value 4, and the difference 10 has place value 2; thus the answer is 4 - 2 + 1 = 3.
Some C code for my attempt
// \return the value X such that n1 should be considered equal to n2 whenever sigfigs is less than X.
int deltaSigFigs(double n1, double n2) {
if (n1 == n2 || (isnan(n1) && isnan(n2))) {
return INT_MAX;
} else if (!isfinite(n1) || !isfinite(n2)) {
// Handled the case of Inf == Inf and -Inf == -Inf above.
return 0;
}
double delta = fabs(n1 - n2);
// Find absolute value of larger-in-magnitude number.
double abig = fmax(fabs(n1), fabs(n2));
// Say N is represented as m * 10^e (m possibly negative).
// Then the number of sigfigs is the difference in exponents
// between the largest in magnitude, and the delta.
double exp = floor(log10(abig));
double expDelta = floor(log10(delta));
// expDelta may be larger than exp, for example deltaSigFigs(8, -8) computes a delta of 16.
// Never return less than 1.
if (expDelta > exp) return 1;
return (int)exp - (int)expDelta + 1;
}
Thank you for any help!

Evenly space n items over m iterations

For context, this is to control multiple stepper motors simultaneously in a high-accuracy application.
Problem statement
Say I have a loop that will run i iterations. Over the course of those iterations, expression E_x should evaluate to true x times (x <= i is guaranteed).
Requirements
- E_x must evaluate to true exactly x times
- E_x must evaluate to true at more or less evenly spaced intervals*
* "evenly spaced intervals" means that the maximum interval size is minimized
Examples
For: i = 10, x = 7
E_x will be true on iterations marked 1: 1101101101
For: i = 10, x = 3
E_x will be true on iterations marked 1: 0010010010
For: i = 10, x = 2
E_x will be true on iterations marked 1: 0001000100
What is the best (or even "a good") way to have E_x evaluate to true at evenly spaced intervals while guaranteeing that it is true exactly x times?
This question is close to mine, however it assumes that E_x will always evaluate to true in the 1st and last iterations, which does not meet my requirements (see 2nd example above).
I'll use a bit different naming convention: let's there by T intervals [1..T] and N events to be fired. Also let's solve the problem as a cyclic one. To do the let's add one fake step at the end that we are guaranteed to fire event at (and this will be also the event at time 0 i.e. before the cycle). So my T is your i+1 and my N is your x+1.
If you divide T by N with reminder you'll get T = w*N + r. If r=0 the case is trivial. If r != 0 the best you can achieve is r intervals of size w+1 and (N-r) intervals of size w. The fast and simple but good enough solution would be something like this (pseudocode):
events = []
w = T / N
r = T % N
current = 0
for(i = 1; i<=N; i++) {
current += w;
if (i <= r)
current += 1;
events[i] = current;
}
You can see that the last value in the array will be T as was promised by our re-statement as a cyclic problem. It will be T because over the cycle we'll add w to current N times and add r times 1, so the sum will be w*N+r which is T.
The main drawback of this solution is that all the "long" intervals will be at the start while all the "short" interval will be at the end.
You can spread intervals more evenly if you are a bit smarter. And the resulting logic will be essentially the same as it is behind Bresenham's line algorithm referenced in comments. Imagine you are drawing a line on a plane, where X-axis represents time and Y-axis represents events, from (0,0) (which is the 0-th event, before your timeframe) to (i+1, x+1) (which is the x+1-th event, just after your timeframe). The moment to raise an event is when you switch to the next Y i.e. draw the first pixel at a given Y.
If you want to do x increments over n iterations, you can do it like this:
int incCount = 0;
int iterCount = 0;
boolean step() {
++iterCount;
int nextCount = (iterCount*x + n/2) / n; // this is rounding division
if (nextCount > incCount) {
++incCount;
return true;
}
else {
return false;
}
}
That's the easy-to-understand way. If you're on an embedded CPU where division is more expensive, you can accomplish exactly the same thing like this:
int accum = n/2;
boolean step() {
accum+=x;
if (accum >= n) {
accum-=n;
return true;
}
else {
return false;
}
}
The total amount added to accum here is iterCount*x + n/2 just like the first example, but the division is replaced with an incremental repeated subtraction. This is the way that Bresenham's line drawing algorithm works.

Matthews Correlation Coefficient yielding values outside of [-1,1]

I'm using the formula found on Wikipedia for calculating Matthew's Correlation Coefficient. It works fairly well, most of the time, but I'm running into problems in my tool's implementation, and I'm not seeing the problem.
MCC = ((TP*TN)-(FP*FN))/sqrt(((TP + FP)( TP + FN )( TN + FP )( TN + FN )))
Where TP, TN, FP, and FN are the non-negative, integer counts of the appropriate fields.
Which should only return values $\epsilon$ [-1,1]
My implementation is as follows:
double ret;
if ((TruePositives + FalsePositives) == 0 || (TruePositives + FalseNegatives) == 0 ||
( TrueNegatives + FalsePositives) == 0 || (TrueNegatives + FalseNegatives) == 0)
//To avoid dividing by zero
ret = (double)(TruePositives * TrueNegatives -
FalsePositives * FalseNegatives);
else{
double num = (double)(TruePositives * TrueNegatives -
FalsePositives * FalseNegatives);
double denom = (TruePositives + FalsePositives) *
(TruePositives + FalseNegatives) *
(TrueNegatives + FalsePositives) *
(TrueNegatives + FalseNegatives);
denom = Math.Sqrt(denom);
ret = num / denom;
}
return ret;
When I use this, as I said it works properly most of the time, but for instance if TP=280, TN = 273, FP = 67, and FN = 20, then we get:
MCC = (280*273)-(67*20)/sqrt((347*300*340*293)) = 75100/42196.06= (approx) 1.78
Is this normal behavior of Matthews Correlation Coefficient? I'm a programmer by trade, so statistics aren't a part of my formal training. Also, I've looked at questions with answers, and none of them discuss this behavior. Is it a bug in my code or in the formula itself?
The code is clear and looks correct. (But one's eyes can always deceive.)
One issue is a concern whether the output is guaranteed to lie between -1 and 1. Assuming all inputs are nonnegative, though, we can round the numerator up and the denominator down, thereby overestimating the result, by zeroing out all the "False*" terms, producing
TP*TN / Sqrt(TP*TN*TP*TN) = 1.
The lower limit is obtained similarly by zeroing out all the "True*" terms. Therefore, working code cannot produce a value larger than 1 in size unless it is presented with invalid input.
I therefore recommend placing a guard (such as an Assert statement) to assure the inputs are nonnegative. (Clearly it matters not in the preceding argument whether they are integral.) Place another assertion to check that the output is in the interval [-1,1]. Together, these will detect either or both of (a) invalid inputs or (b) an error in the calculation.

Probabilistic Sieve of Eratosthenes

Consider the following algorithm.
function Rand():
return a uniformly random real between 0.0 and 1.0
function Sieve(n):
assert(n >= 2)
for i = 2 to n
X[i] = true
for i = 2 to n
if (X[i])
for j = i+1 to n
if (Rand() < 1/i)
X[j] = false
return X[n]
What is the probability that Sieve(k) returns true as a function of k ?
Let's define a series of random variables recursively:
Let Xk,r denote the indicator variable, taking value 1 iff X[k] == true by the end of the iteration in which the variable i took value r.
In order to have fewer symbols and since it makes more intuitive sense with the code, we'll just write Xk,i which is valid although would have been confusing in the definition since i taking value i is confusing when the first refers to the variable in the loop and the latter to the value of the variable.
Now we note that:
P(Xk,i ~ 0) = P(Xk,i-1 ~ 0) + P(Xk,i-1 ~ 1) * P(Xk-1,i-1 ~ 1) * 1/i
(~ is used in place of = just to make it understandable, since = would otherwise take two separate meanings and looks confusing).
This equality holds by virtue of the fact that either X[k] was false at the end of the i iteration either because it was false at the end of the i-1, or it was true at that point, but in that last iteration X[k-1] was true and so we entered the loop and changed X[k] with probability of 1/i. The events are mutually exclusive, so there is no intersection.
The base of the recursion is simply the fact that P(Xk,1 ~ 1) = 1 and P(X2,i ~ 1) = 1.
Lastly, we note simply that P(X[k] == true) = P(Xk,k-1 ~ 1).
This can be programmed rather easily. Here's a javascript implementation that employs memoisation (you can benchmark if using nested indices is better than string concatenation for the dictionary index, you could also redesign the calculation to maintain the same runtime complexity but not run out of stack size by building bottom-up and not top-down). Naturally the implementation will have a runtime complexity of O(k^2) so it's not practical for arbitrarily large numbers:
function P(k) {
if (k<2 || k!==Math.round(k)) return -1;
var _ = {};
function _P(n,i) {
if(n===2) return 1;
if(i===1) return 1;
var $ = n+'_'+i;
if($ in _) return _[$];
return _[$] = 1-(1-_P(n,i-1) + _P(n,i-1)*_P(n-1,i-1)*1/i);
}
return _P(k,k-1);
}
P(1000); // 0.12274162882390949
More interesting would be how the 1/i probability changes things. I.e. whether or not the probability converges to 0 or to some other value, and if so, how changing the 1/i affects that.
Of course if you ask on mathSE you might get a better answer - this answer is pretty simplistic, I'm sure there is a way to manipulate it to acquire a direct formula.

Programming Interview Question / how to find if any two integers in an array sum to zero?

Not a homework question, but a possible interview question...
Given an array of integers, write an algorithm that will check if the sum of any two is zero.
What is the Big O of this solution?
Looking for non brute force methods
Use a lookup table: Scan through the array, inserting all positive values into the table. If you encounter a negative value of the same magnitude (which you can easily lookup in the table); the sum of them will be zero. The lookup table can be a hashtable to conserve memory.
This solution should be O(N).
Pseudo code:
var table = new HashSet<int>();
var array = // your int array
foreach(int n in array)
{
if ( !table.Contains(n) )
table.Add(n);
if ( table.Contains(n*-1) )
// You found it.;
}
The hashtable solution others have mentioned is usually O(n), but it can also degenerate to O(n^2) in theory.
Here's a Theta(n log n) solution that never degenerates:
Sort the array (optimal quicksort, heap sort, merge sort are all Theta(n log n))
for i = 1, array.len - 1
binary search for -array[i] in i+1, array.len
If your binary search ever returns true, then you can stop the algorithm and you have a solution.
An O(n log n) solution (i.e., the sort) would be to sort all the data values then run a pointer from lowest to highest at the same time you run a pointer from highest to lowest:
def findmatch(array n):
lo = first_index_of(n)
hi = last_index_of(n)
while true:
if lo >= hi: # Catch where pointers have met.
return false
if n[lo] = -n[hi]: # Catch the match.
return true
if sign(n[lo]) = sign(n[hi]): # Catch where pointers are now same sign.
return false
if -n[lo] > n[hi]: # Move relevant pointer.
lo = lo + 1
else:
hi = hi - 1
An O(n) time complexity solution is to maintain an array of all values met:
def findmatch(array n):
maxval = maximum_value_in(n) # This is O(n).
array b = new array(0..maxval) # This is O(1).
zero_all(b) # This is O(n).
for i in index(n): # This is O(n).
if n[i] = 0:
if b[0] = 1:
return true
b[0] = 1
nextfor
if n[i] < 0:
if -n[i] <= maxval:
if b[-n[i]] = 1:
return true;
b[-n[i]] = -1
nextfor
if b[n[i]] = -1:
return true;
b[n[i]] = 1
This works by simply maintaining a sign for a given magnitude, every possible magnitude between 0 and the maximum value.
So, if at any point we find -12, we set b[12] to -1. Then later, if we find 12, we know we have a pair. Same for finding the positive first except we set the sign to 1. If we find two -12's in a row, that still sets b[12] to -1, waiting for a 12 to offset it.
The only special cases in this code are:
0 is treated specially since we need to detect it despite its somewhat strange properties in this algorithm (I treat it specially so as to not complicate the positive and negative cases).
low negative values whose magnitude is higher than the highest positive value can be safely ignored since no match is possible.
As with most tricky "minimise-time-complexity" algorithms, this one has a trade-off in that it may have a higher space complexity (such as when there's only one element in the array that happens to be positive two billion).
In that case, you would probably revert to the sorting O(n log n) solution but, if you know the limits up front (say if you're restricting the integers to the range [-100,100]), this can be a powerful optimisation.
In retrospect, perhaps a cleaner-looking solution may have been:
def findmatch(array num):
# Array empty means no match possible.
if num.size = 0:
return false
# Find biggest value, no match possible if empty.
max_positive = num[0]
for i = 1 to num.size - 1:
if num[i] > max_positive:
max_positive = num[i]
if max_positive < 0:
return false
# Create and init array of positives.
array found = new array[max_positive+1]
for i = 1 to found.size - 1:
found[i] = false
zero_found = false
# Check every value.
for i = 0 to num.size - 1:
# More than one zero means match is found.
if num[i] = 0:
if zero_found:
return true
zero_found = true
# Otherwise store fact that you found positive.
if num[i] > 0:
found[num[i]] = true
# Check every value again.
for i = 0 to num.size - 1:
# If negative and within positive range and positive was found, it's a match.
if num[i] < 0 and -num[i] <= max_positive:
if found[-num[i]]:
return true
# No matches found, return false.
return false
This makes one full pass and a partial pass (or full on no match) whereas the original made the partial pass only but I think it's easier to read and only needs one bit per number (positive found or not found) rather than two (none, positive or negative found). In any case, it's still very much O(n) time complexity.
I think IVlad's answer is probably what you're after, but here's a slightly more off the wall approach.
If the integers are likely to be small and memory is not a constraint, then you can use a BitArray collection. This is a .NET class in System.Collections, though Microsoft's C++ has a bitset equivalent.
The BitArray class allocates a lump of memory, and fills it with zeroes. You can then 'get' and 'set' bits at a designated index, so you could call myBitArray.Set(18, true), which would set the bit at index 18 in the memory block (which then reads something like 00000000, 00000000, 00100000). The operation to set a bit is an O(1) operation.
So, assuming a 32 bit integer scope, and 1Gb of spare memory, you could do the following approach:
BitArray myPositives = new BitArray(int.MaxValue);
BitArray myNegatives = new BitArray(int.MaxValue);
bool pairIsFound = false;
for each (int testValue in arrayOfIntegers)
{
if (testValue < 0)
{
// -ve number - have we seen the +ve yet?
if (myPositives.get(-testValue))
{
pairIsFound = true;
break;
}
// Not seen the +ve, so log that we've seen the -ve.
myNegatives.set(-testValue, true);
}
else
{
// +ve number (inc. zero). Have we seen the -ve yet?
if (myNegatives.get(testValue))
{
pairIsFound = true;
break;
}
// Not seen the -ve, so log that we've seen the +ve.
myPositives.set(testValue, true);
if (testValue == 0)
{
myNegatives.set(0, true);
}
}
}
// query setting of pairIsFound to see if a pair totals to zero.
Now I'm no statistician, but I think this is an O(n) algorithm. There is no sorting required, and the longest duration scenario is when no pairs exist and the whole integer array is iterated through.
Well - it's different, but I think it's the fastest solution posted so far.
Comments?
Maybe stick each number in a hash table, and if you see a negative one check for a collision? O(n). Are you sure the question isn't to find if ANY sum of elements in the array is equal to 0?
Given a sorted array you can find number pairs (-n and +n) by using two pointers:
the first pointer moves forward (over the negative numbers),
the second pointer moves backwards (over the positive numbers),
depending on the values the pointers point at you move one of the pointers (the one where the absolute value is larger)
you stop as soon as the pointers meet or one passed 0
same values (one negative, one possitive or both null) are a match.
Now, this is O(n), but sorting (if neccessary) is O(n*log(n)).
EDIT: example code (C#)
// sorted array
var numbers = new[]
{
-5, -3, -1, 0, 0, 0, 1, 2, 4, 5, 7, 10 , 12
};
var npointer = 0; // pointer to negative numbers
var ppointer = numbers.Length - 1; // pointer to positive numbers
while( npointer < ppointer )
{
var nnumber = numbers[npointer];
var pnumber = numbers[ppointer];
// each pointer scans only its number range (neg or pos)
if( nnumber > 0 || pnumber < 0 )
{
break;
}
// Do we have a match?
if( nnumber + pnumber == 0 )
{
Debug.WriteLine( nnumber + " + " + pnumber );
}
// Adjust one pointer
if( -nnumber > pnumber )
{
npointer++;
}
else
{
ppointer--;
}
}
Interesting: we have 0, 0, 0 in the array. The algorithm will output two pairs. But in fact there are three pairs ... we need more specification what exactly should be output.
Here's a nice mathematical way to do it: Keep in mind all prime numbers (i.e. construct an array prime[0 .. max(array)], where n is the length of the input array, so that prime[i] stands for the i-th prime.
counter = 1
for i in inputarray:
if (i >= 0):
counter = counter * prime[i]
for i in inputarray:
if (i <= 0):
if (counter % prime[-i] == 0):
return "found"
return "not found"
However, the problem when it comes to implementation is that storing/multiplying prime numbers is in a traditional model just O(1), but if the array (i.e. n) is large enough, this model is inapropriate.
However, it is a theoretic algorithm that does the job.
Here's a slight variation on IVlad's solution which I think is conceptually simpler, and also n log n but with fewer comparisons. The general idea is to start on both ends of the sorted array, and march the indices towards each other. At each step, only move the index whose array value is further from 0 -- in only Theta(n) comparisons, you'll know the answer.
sort the array (n log n)
loop, starting with i=0, j=n-1
if a[i] == -a[j], then stop:
if a[i] != 0 or i != j, report success, else failure
if i >= j, then stop: report failure
if abs(a[i]) > abs(a[j]) then i++ else j--
(Yeah, probably a bunch of corner cases in here I didn't think about. You can thank that pint of homebrew for that.)
e.g.,
[ -4, -3, -1, 0, 1, 2 ] notes:
^i ^j a[i]!=a[j], i<j, abs(a[i])>abs(a[j])
^i ^j a[i]!=a[j], i<j, abs(a[i])>abs(a[j])
^i ^j a[i]!=a[j], i<j, abs(a[i])<abs(a[j])
^i ^j a[i]==a[j] -> done
The sum of two integers can only be zero if one is the negative of the other, like 7 and -7, or 2 and -2.

Resources