18 February 2014

Fork me on GitHub

  • Divide and conquer
    • Selection - derandomization (Blum, Floyd, Pratt, Rivest, Tarjan)
  • Back-tracking
    • Improved exponential time algorithms
    • 1/2 of DP

In QuickSelect, the rank of a good pivot in the sorted list is betweeen \( \alpha n \) and \( (1 - \alpha) n \), where there are \( n \) elements. The hope of the derandomized technique is to find a pivot that is "almost media" in linear time.

Consider breaking the \( n \) elements into \( m \) groups of size \( n / m \). Take the median in every group, then the median of the medians. If you take \( m = \sqrt{n} \), you get an \( O(n \log \log n) \) technique. If you take \( m = \log{n} \), you get an \( O(n \log ^* n) \) technique. The trick is to take \( m = n / 5 \), or an other odd larger than 3. \( n / 10 \) of the group medians are less than our pivot. 3 elements of each such group are smaller than our pivot, so there are \( 3n/10 \) elements smaller than our pivot. Applying a symmetric argument for the larger elements, we can get \( \alpha = 0.3 \). Then we can use the same analysis as last time to get an \( O(n) \) algorithm. The recurrence looks like \[ T(n) = T(n/5) + T(.7 n) + O(n) \]

Backtracking

A general approach to solving constrained optimization problems. Unfortunately, this algorithm usually gives you an exponential algorithm. Fortunately, the exponential is usually better than naive exhaustive search.

Independent Set

Find the maximum subset of the vertices of a graph such that no two nodes are adjacent.

Exhaustive search would take \( O(2^n poly(n)) \) time. With backtracking, we can prune branches that are inconsistent, sub-optimal, or redundant. Consider a local decision: to include the next node or exclude it.

def IndependentSet(G):
  if |V| == 0: return 0
  if |v| == 1: return 1
  pick x in V
  In <- 1 + IndependentSet(G - {x} - N(x))
  Out <- IndependentSet(G - {x})
  return max(In, Out)

The recurrence for the above looks something like \[ T(n) = 2 T(n - 1) + O(1) \] This has complexity around \( 2 ^ n \).

Modified algorithm:

def IndependentSet(G):
  if |V| == 0: return 0
  if |v| == 1: return 1
  pick x in V
  if x has neighbors:
    In <- 1 + IndependentSet(G - {x} - N(x))
    Out <- IndependentSet(G - {x})
    return max(In, Out)
  else:
    // It is definitely in the independent set. 
    return 1 + IndependentSet(G - {x})

The recurrence looks like \[ T(n) \leq T(n-1) + T(n -2) + O(1) \] The above has complexity \( O (((1 + \sqrt{5})/2)^n) \).