algorithms – Nested loop complexity

I am working through MIT 6.006 OpenCourseWare as taught in Fall 2011. Problem 1.2c asks for the time complexity of an algorithm which finds a peak element (i.e. all neighbors are less than or equal) of an M x N matrix. My solution does not match theirs and appears to hinge on the complexity of a nested loop.

The algorithm creates a cross which divides the matrix into four “subproblems”. It finds the max on the cross, checks neighbors, and recurses as needed:

def algorithm3(problem, bestSeen = None, trace = None):
    # if it's empty, we're done 
    if problem.numRow <= 0 or problem.numCol <= 0:
        return None

    midRow = problem.numRow // 2
    midCol = problem.numCol // 2

    # first, get the list of all subproblems
    subproblems = ()

    (subStartR1, subNumR1) = (0, midRow)
    (subStartR2, subNumR2) = (midRow + 1, problem.numRow - (midRow + 1))
    (subStartC1, subNumC1) = (0, midCol)
    (subStartC2, subNumC2) = (midCol + 1, problem.numCol - (midCol + 1))

    subproblems.append((subStartR1, subStartC1, subNumR1, subNumC1))
    subproblems.append((subStartR1, subStartC2, subNumR1, subNumC2))
    subproblems.append((subStartR2, subStartC1, subNumR2, subNumC1))
    subproblems.append((subStartR2, subStartC2, subNumR2, subNumC2))

    # find the best location on the cross (the middle row combined with the
    # middle column)
    cross = ()

    cross.extend(crossProduct((midRow), range(problem.numCol)))
    cross.extend(crossProduct(range(problem.numRow), (midCol)))

    crossLoc = problem.getMaximum(cross, trace)
    neighbor = problem.getBetterNeighbor(crossLoc, trace)

    # update the best we've seen so far based on this new maximum
    if bestSeen is None or problem.get(neighbor) > problem.get(bestSeen):
        bestSeen = neighbor
        if not trace is None: trace.setBestSeen(bestSeen)

    # return if we can't see any better neighbors
    if neighbor == crossLoc:
        if not trace is None: trace.foundPeak(crossLoc)
        return crossLoc

    # figure out which subproblem contains the largest number we've seen so
    # far, and recurse
    sub = problem.getSubproblemContaining(subproblems, bestSeen)
    newBest = sub.getLocationInSelf(problem, bestSeen)
    if not trace is None: trace.setProblemDimensions(sub)
    result = algorithm3(sub, newBest, trace)
    return problem.getLocationInSelf(sub, result)

The instructor provides the complexity for getMaximum as O(len(locations)), getBetterNeighbor and getLocationInSelf as O(1), getSubproblemContaining as O(len(boundList)), and all trace calls as O(1). The crossProduct is computed as:

def crossProduct(list1, list2):
    answer = ()
    for a in list1:
        for b in list2:
            answer.append ((a, b))
    return answer

The solution states, “a single call of the function (not counting the recursive call) does work proportional to m + n.” I don’t understand this.

Isn’t crossProduct O(mn)?

My reasoning is that for an M x N matrix, getMaximum must traverse the dividing cross (one row, one column) which contributes O(m + n). The getSubproblemContaining contributes something linear, O(m) or O(n). Everything else besides crossProduct is O(1), the complexity of crossProduct not being provided, so that the recurrence relation is

T(m, n) = O(mn) + O(m + n) + cO(n) + T(m/2, n/2)   for some constant c
        = O(mn) + T(m/2, n/2)

The recurrence reduces via the geometric series to O(m + n),

T(m, n) = O(mn) + O(m + n)
        = O(mn) 

which yields T(n,n) = O(n^2). The solution provided is O(n). The crossProduct term appears to be the discrepancy.

algorithms – Converting Decimal Numbers between 0 and 1 to Binary

I’ve been playing around with a program I wrote that converts decimal numbers to binary numbers and i’ve noticed that eventually, after applying the algorithm (multiply by 2, subtract 1 if greater than or equal to 1), to convert a decimal to binary, the results turn strange likely due to floating point imprecision.

For example, the following is a result you might find when applying the algorithm:

enter image description here

The number 0.531904 multiplied by 2 and then subtracted by 1 should result in 0.063708 instead of what is highlighted. Successive instances of this cause the error to eventually propagate to a much greater margin after more iterations.

Thus, I have made 3 observations:

  1. For a decimal between 0 and 1 with “N” places after the point, multiplying it by 2 should never make it more than “N” places. (e.g. multiplying 0.022, where N=3, by any power of 2 should never give it a fourth place etc.)

  2. For a decimal number between 0 and 1 with “N” decimal places beyond the dot. (e.g. 0.022 has N=3 and 0.0101 has N=4) if the binary representation is repeating, then the repeating portion should be no longer than 10^N digits.

  3. For a decimal number between 0 and 1 with the last (rightmost) digit being {1,2,3,4, ,6,7,8,9} it will always have a repeating representation in binary. It will only not have a repeating representation if the last digit is 5.

My Questions are as follows:

  1. Are these observations true?

  2. If so, is rounding the number to “N” decimal places at every iteration step an appropriate way to fix the problem of precision?

  3. Can someone confirm the result I obtained that 0.002992 has a repeating portion that is 12500 digits long?

algorithms – “what does the 1 to 10 mean?” FOR number ← 1 TO 10

In Python, this is typically written

for number in range(1, 10):  # or range(1, 11) depending on interpretation
    pass  # do stuff here

where pass is replaced with the block you want to execute.

Note that I wrote range(1,10) which gives

number = 1, 2, 3, 4, 5, 6, 7, 8, 9

in turn, i.e. the endpoint (10) is exclusive. It could mean that the 1 TO 10 should be interpreted inclusive, i.e.

number = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

but out of context, this is difficult to say.

In C-like languages, this often looks like

for (int i = 0; i < 10; i++) {
    // do stuff here
}

Again, maybe the i < 10 should be i <= 10.

The syntax in the exercise looks a lot like Pascal, which uses

begin
   for number := 1 to 10 do
   begin
      // do stuff here
   end;
end.

which I believe is inclusive.

algorithms – Probability of false positive for lookup in hashtable

I am going over Mikkel Thorups notes on hashing, as revision, and I came to the following exercise that i cannot see how to tackle (even initially – I know this is not ideal for a question.)

$$
begin{array}{l}text { Exercise } 2.5 \ text { With } s: U rightarrowleft(n^{3}right) text { and } h: U rightarrow(n) text { independent universal hash functions, for a } \ text { given } x in U backslash S, text { what is the probability of a false positive when we search } x,\ text { that is, what is the } text { probability that there is a key } y in S text { such that }\ h(y)=h(x) text { and } s(y)=s(x) ?end{array}
$$

Any pointers on how to approach this are appreciated

algorithms – 3SAT and directed graph

Given a 3SAT instance (a Boolean expression in three conjunctural normal form), we draw a directed graph, where for each Boolean variable $x_{i}$ we have the nodes $x_{i}$ and $!x_{i}$; for each clause, for example $left(x_{a} vee x_{b} vee x_{c}right)$, we draw the following arrows $!x_{a}x_{b}$, $!x_{a}x_{c}$, $!x_{b}x_{a}$, $!x_{b}x_{c}$, $!x_{c}x_{a}$, $!x_{c}x_{b}$.

Is it possible understand from the graph if there is a variable $x_{i}$ such that $x_{i}Leftrightarrow !x_{i}$ ($!x_{i}$ is $notleft(x_{i}right)$)?

algorithms – Minimize range of distances between two sets of points

I have two sets of n points each in 2D Cartesian coordinates. I want to find a one-to-one pairing between the points in sets A and B such that the range of distances between the points is the smallest.

For example, consider $n=3$, $A_1 = (0,0)$, $A_2 = (1,0)$, $A_3 = (3,0)$, $B_1 = (1,1)$, $B_2 = (3,2)$, $B_3 = (-1,0)$.
The best pairing will is $A_1 text{ and } B_1$, $A_2 text{ and } B_3$, $A_3 text{ and } B_2$, because the distances are $(sqrt{2}, 2, 2)$, giving the smallest range of $2 – sqrt2$.

Ideally, I am looking for a solution which is able to solve the problem quickly (<5 seconds) for $n=300$.

algorithms – Knapsack Problem with Constraints on Item Values

Given $n$ items with weights $w_1,…,w_n$ and values $v_1,…,v_n$, and a weight limit $W$, the purpose is still maximizing the total value of items to be carried (while not exceeding the weight limit). Now, a new constraint is, once an item with value $v_i$ is taken, all items whose value is greater than $v_i$ must also be taken. (It is okay to assume that all $v_i$‘s are different)

My purpose is to achieve this in $O(n)$ time, and here is my attempt (suppose the input is an array $A$ of tuples $(w_i, v_i)$):

  1. Calculate total weight of the items: $W_{mathrm{total}}gets sum_{i=1}^n w_i$;

  2. while $(W_{mathrm{total}} > W)$ do:

    2.1 $pgets$ median of values in $A$;

    2.2 $Rgets$ items whose value is greater than $p$;

    2.3 $Lgets Asetminus R$; (items whose value is smaller than $p$)

    2.4 $W_Rgets$ $sum_{A(i)in R}w_i$;

    2.5 $W_{mathrm{total}}gets W_R$;

    2.6 $Agets R$;

  3. $Wgets W- W_{mathrm{total}}$; (the remaining capacity)

  4. Repeat step 2 for the array $L$, generating the array $L’$;

  5. Return $L’cup A$;

Notice that the algorithm for finding the median costs linear time.

I presume that my algorithm costs $O(n)$ time since, for every iteration in each while loop, the input size halves–but I am not 100% confident of that. So does this algorithm really cost linear time? If not, what amendments can be made, or is there a general idea for designing such an algorithm that costs linear time? Any help will be much appreciated! 🙂

algorithms – How to identify certain pathes in directed graph?

For the lack of a better way to explain my problem, I’ve drawn an example directed graph as you can see below. The edges are annotated with letters. What algorithm could achieve such an annotation?

My approach right now would first find all possible paths through the graph. Then, following every path, I would count how often each edge was visited. The number of visitations would then indicate the different sub graphs (A-D). But this would already stop working for a symmetric graph.

I feel like I’m missing the obvious solution. Could anyone please help?

Example Graph

algorithms – How to write a method that takes two int parameters and return a string?

How do I write a method that takes two int parameters, a and b, and returns a String in the form a=q*b+r where q is the quotient from division and r is the remainder?
Also how do I write a method that takes an int parameter for the number of tokens you have had and prints to the console the number of companions, spells, and resources you can trade for. You can trade in 15 tokens for a companion, 7 tokens for a spell, or 3 tokens for a resource? Thanks!
Photo includes more info:

algorithms and the sequencing of numbers given a value

The numbers in the table below are the result of executing an algorithm that has one parameter N, a non-negative integer, and produces sequences of integers as outputs. For values of N from 0 to 5, the algorithm produces the following sequences of numbers as outputs.

the following outputs calculated are
N/ Outputs
0/ 0 2
1/ 3 5 7 9
2/ 6 8 10 12 14 16
3/ 9 11 13 15 17 19 21 23
4/ 12 14 16 18 20 22 24 26 28 30
5/ 15 17 19 21 23 25 27 29 31 33 35 37
N=6

I just started a course and I dont understand. I get the pattern differences and I understand all the patterns that are formed such as each outputs first number is a multiple of three and then the lists rise by two for each output given. When I put this doown off of what I was given as a reference in the class it tells us to create n algorithm for this but we have not been given but a few ways to do this so I tried: N^2 -20
which would be 36-0=36
step two: N^2-2
1
which would be 6^2 or 36-2=34
Step 3: N^2-22
which would be 6^2 or 36 -4=32
Step 4: N^2-2
3
which would be 6^2 or 36-6=30
Step 5: 6^2-24
which would be 6^2 or 36-8=28
Step 5: 6^2-2
5
which would be 6^2 or 36-10 =26

N/ Outputs
0/36
1/34
2/32
3/30
4/28
5/26
So my outputs come out as 36 34 32 30 28 26
Is this correct and if not then where am I going wrong