Greedy Algorithms

A greedy algorithm arrives at a solution by making a sequence of choices, each of which simply looks the best at the moment. The hope is that locally-optimal choices will lead to a globally-optimal solution.

Making Change

def MakingChange(x):
Coins = {5, 10, 25, 100, 200}
Sum = 0
while Sum != x:
Let c in Coins be the largest denomination such that Sum + c <= x
if there is no such denomination:
return "No Solution"
Add c to the change that will be returned
Sum = Sum + c

The 0, 1 - Knapsack Problem

Find a greedy algorithm to solve the following problem.

input:

  • nn objects such that object ii (1 \leq i \leq n) has a positive value viv_i and a positive weight wiw_i.
  • A maximum weight WW.

output: A vector X=(x1,x2,...,xn)X = (x_1, x_2, ..., x_n) such that

  • 0xi10 \leq x_i \leq 1
  • The total value x1v1+x2v2+...+xnvnx_1v_1+x_2v_2+ ... + x_nv_n is maximized.
  • The total weight is not too heavy: x1w1+x2w2+...+xnwnWx_1w_1 + x_2w_2 + ... + x_nw_n \leq W.

Lemma

If the objects are selected in order of decreasing viwi\frac{v_i}{w_i}, then the greedy choice finds an optimal solution.

Algorithm

  1. Compute all the viwi\frac{v_i}{w_i}
  2. Sort the objects in decreasing order of viwi\frac{v_i}{w_i} (use MergeSort)
  3. Build the solution by applying the greedy choice with respect to decreasing order of viwi\frac{v_i}{w_i}.

Total time: O(nlog(n))O(n log(n))

Minimum Spanning Tree

We are given edge G=(V,E)G = (V, E) that is undirected and connected. Each edge u,vE{u, v} \in E has a weight wt(u,v)wt (u, v).

We want a compute a subgraph GofGG' of G such that:

  • The vertex set of GisVG' is V,
  • GG' is connected,
  • and weight(G)weight(G') is minimum, where
    • weight(G)weight(G') = sum of weights of edges in GG'.

GG' is called a Minimum Spanning Tree of G (MST of G).

Lemma

Let G=(V,E)G = (V, E) be an undirected and connected graph, where each edge u,vE{u,v} \in E has a weight wt(u,v)wt(u,v).

Split VV into AA and BB. Let u,vE{u,v} \in E be a shortest edge connecting AA and BB. then there is an MST of GG that contains u,v{u,v}.

From the previous lemma, any algorithm that follows this greedy scheme is guaranteed to work:

  1. X = {}
  2. Repeat until X=V1|X| = |V| - 1
    • Pick a set SS such that XX has no edge between SS and V/SV/S.
    • Let eEe \in E be a minimum-weight edge between SS and V/SV/S.
    • X=XeX = X \cup {e}

Union-Find Data Structure

Before presenting a first algorithm to compute an MST, we first open a parenthesis and study a data structure called Union-find.

Given nn sets, each of size one, process a sequence of operation, where each operation is one of:

def union (A,B,C):
Set C = A U B
A = {}
B = {}
def find (x):
Return the name of the set that contains x

The sequence consists of n1n-1 Union operations, mm Find operations. This can be done in any arbitrary order.

We store each set in a list:

  • the list has a pointer to the head and a pointer to the tail
  • the first node stores the name of the set and the size of the set
  • each other node stores one element of the set
  • each node uu stores two pointers:
    • next(uu) the next node in the list
    • back(uu) first node in the list

For the Union Function:

  • if size of set AA is larger than BB, append BB to AA. Otherwise append AA to BB.
  • running time O(minA,BO(\mathrm{min}{|A|,|B|}

For the Find function:

  • follow the back pointed from the node storing xx to the head of the list and return the name stored at the head.
  • O(1)O(1)

Total running time:

  • n1n-1 Union operations = $O (n \log{n})
  • Any sequence of n1n-1 Union operations and mm Find operations takes O(m+nlogn)O(m + n \log{n})

Kruskal Algorithm

  • Approach: Maintain a forest. In each step, add an edge of minimum weight that does not create a cycle.
  • Start: At the beginning, each vertex is a (trivial) tree.
  • One Iteration: Combine two trees using an edge of minimum weight
# Input: G = (V,E), where V = {x1, x2, ..., xn} and m = |E|
# Output: A minimum spanning tree of G
def Kruskal(G):
Sort the edges of E by weight using Merge Sort
for i in range(n):
V[i] = x[i]
T = {}
for k in range(m):
Let u[k] and v[k] be the vertices of e[k]
Let i be the index such that u[k] is in V[i]
Let j be the index such that v[k] is in V[j]
if (i != j):
V[i] = Vi[i] union V[j]
V[j] = {}
T = T union {{u[k], v[k]}}
return T

Running time

  • Sorting: O(mlogm)O(m \log{m})
  • First loop: O(n)O(n) time
  • Second for loop:
    • Store TT in a linked list Total time to maintain this list: O(n)O(n) time
    • Store the sets ViV_i using the Union-Find data structure
    • In this second For-Loop, we do
      • 2m2m Find operations
      • n1n-1 Union operations
    • So in total for the second for loop: O(n)+O(m+nlogn)O(n) + O(m + n \log{n})
  • Total running time is O(mlogn)O(m \log{n})

Prim Algorithm

Start:

  • AA is a set consisting of one (arbitrary) vertex of VV
  • TT is an empty set of edges.
  • Q=V/AQ = V/A

One Iteration:

  • Take an edge u,v{u, v} of minimum weight such that uAu \in A and vQv \in Q
  • Add the edge u,v{u, v} to TT
  • Move vv from QQ to AA

Repeat until A=VA = V (i.e. Q=Q={})!

# Input: G = (V,E)
# Output: A minimum spanning tree of G
def Prim(G):
Let r in V be an arbitrary vertex.
A = {r}
T = {}
while A != V:
# Q = V\A
find an edge {u, v} in E of min weight such that u in A and v in Q
A = A union {v}
T = T union {{u,v}}

Finding the edge u,v{u,v} takes O(E)O(|E|) time, so total running time is O(VE)O(|V| \cdot |E|)

To improve running time, we can maintain extra information.

For each vertex yQy \in Q, minweight(y)(y): minimum weight of any edge between y and a vertex of AA. closest(y)(y): vertex xAx \in A for which wt(x,y)=minweight(y)wt(x, y) = \mathrm{minweight}(y). Observe that: a shortest edge u,v{u, v} connecting AA and QQ has weight minyQminweight(y)min_{y\in Q}{\mathrm{minweight}(y)}.

Algorithm

# Input: G = (V , E)
# Output: A minimum spanning tree of G
Let r ∈ V be an arbitrary vertex
A = {r}
T = { }
for each vertex y != r:
minweight(y) = infinity
closest(y) = nil
for each edge {r, y}:
minweight(y) = wt(r, y)
closest(y) = r
Q = V \ {r}
k = 1 # Stores the size of A
while k != n:
Let v be the vertex of Q for which minweight(v) is minimum
u = closest(v)
A = A{v}
Q = Q \ {v}
T = T{{u, v}}
k = k + 1
for each edge {v, y}:
if y ∈ Q and wt(v, y) < minweight(y):
minweight(y) = wt(v, y)
closest(y) = v
return T
  • Store the vertices of QQ in a min-heap.
  • For each vertex vQv \in Q, the key of vv is minweight(v).
  • Store TT in a list.
  • With each vertex of VV, store one bit indicating whether the vertex
  • belongs to AA or to QQ.

Running time:

  • Up to the while loop: O(n)O(n) time (this includes the time to build the heap).
  • One iteration of the while-loop:
    • extract min: O(log(n))O(\log(n)) time
    • At most degree(v)\mathrm{degree(v)} many decrease key operations: O(degree(v)logn)O(\mathrm{degree}(v) · \log{n}) time
  • Total time for the while-loop: $O (m \log{n})