0% found this document useful (0 votes)
6 views

Greedy Algorithm

Uploaded by

pranshusahu862
Copyright
© © All Rights Reserved
Available Formats
Download as ODT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Greedy Algorithm

Uploaded by

pranshusahu862
Copyright
© © All Rights Reserved
Available Formats
Download as ODT, PDF, TXT or read online on Scribd
You are on page 1/ 4

Greedy Algorithms

Greedy algorithms are a class of algorithms that make locally optimal choices at each stage with the
hope of finding a global optimum. These algorithms are used when the problem has an optimal
substructure and greedy-choice property. In simpler terms, greedy algorithms work by solving a
problem step by step, selecting the best choice available at each step.

1. Introduction to Greedy Algorithms


A greedy algorithm is one that selects the best possible option at each decision point with the hope
that these local optimal choices will lead to a globally optimal solution. Unlike dynamic
programming, greedy algorithms do not reconsider previous choices. If a greedy algorithm doesn't
guarantee the optimal solution, it is typically called a heuristic.
Greedy algorithms are often easier to implement and understand, and they have lower time
complexities compared to other algorithms like dynamic programming and backtracking. However,
the main drawback is that they may not always produce the best solution, as they do not explore all
possible choices, which could potentially lead to a suboptimal solution.

2. Properties of Greedy Algorithms


For a problem to be solvable by a greedy algorithm, it must exhibit the following two properties:
• Greedy-Choice Property: A global optimum can be arrived at by selecting a local optimum.
This means that making the best choice at each step will lead to the overall best solution.
• Optimal Substructure: An optimal solution to the problem contains an optimal solution to
subproblems. This allows the problem to be solved by solving smaller subproblems.
If both properties are satisfied, a greedy algorithm will provide the correct solution. However, if the
problem does not satisfy these properties, a greedy algorithm may not work.

3. Greedy Algorithm Approach


Greedy algorithms follow a simple approach:
1. Initialization: Start with an empty solution or an initial solution.
2. Greedy Selection: At each step, choose the best option available (locally optimal).
3. Feasibility Check: Ensure that the current solution is feasible.
4. Repeat: Continue the process until the problem is solved.

4. Common Greedy Algorithms


4.1 Fractional Knapsack Problem
The Fractional Knapsack problem is a typical example of a problem that can be solved by a greedy
approach. In this problem, we are given a set of items, each with a weight and a value, and we need
to determine the maximum value that can be carried in a knapsack of a fixed capacity. Unlike the
0/1 knapsack problem, we can take fractions of an item in the fractional knapsack.
Greedy Strategy: At each step, select the item with the highest value-to-weight ratio and add it to
the knapsack. Continue until the knapsack is full or all items are processed.
Algorithm:
1. Sort the items by their value-to-weight ratio in descending order.
2. Take as much of the first item as possible.
3. Move to the next item and repeat until the knapsack is full or all items are taken.
Time Complexity: Sorting the items takes O(nlogn), where n is the number of items.
Python Example:
python
Copy code
def fractional_knapsack(weights, values, capacity):
n = len(weights)
items = [(values[i], weights[i], values[i] / weights[i]) for i in range(n)]
items.sort(key=lambda x: x[2], reverse=True)

total_value = 0
for value, weight, ratio in items:
if capacity >= weight:
capacity -= weight
total_value += value
else:
total_value += ratio * capacity
break
return total_value

4.2 Huffman Coding


Huffman coding is a lossless data compression algorithm used to compress data. The algorithm is
based on a frequency analysis of characters in a given input. The characters that appear more
frequently are assigned shorter codes, while characters that appear less frequently are assigned
longer codes.
Greedy Strategy: Build a binary tree by repeatedly merging the two nodes with the least
frequencies until all characters are encoded.
Steps:
1. Create a priority queue and insert all characters with their frequencies.
2. Repeatedly remove the two nodes with the lowest frequencies and merge them into a new
node.
3. Insert the new node back into the priority queue until there is only one node remaining.
Time Complexity: O(nlogn), where n is the number of characters.
Python Example:
python
Copy code
import heapq
from collections import defaultdict

def huffman_encoding(data):
if not data:
return "", {}

frequency = defaultdict(int)
for char in data:
frequency[char] += 1

heap = [[weight, [char, ""]] for char, weight in frequency.items()]


heapq.heapify(heap)

while len(heap) > 1:


lo = heapq.heappop(heap)
hi = heapq.heappop(heap)
for pair in lo[1:]:
pair[1] = '0' + pair[1]
for pair in hi[1:]:
pair[1] = '1' + pair[1]
heapq.heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])

huffman_tree = heap[0]
return ''.join([pair[1] for pair in huffman_tree[1:]]), {pair[0]: pair[1]
for pair in huffman_tree[1:]}

4.3 Activity Selection Problem


The Activity Selection problem is a classic example of a greedy algorithm. Given a set of activities
with start and finish times, the task is to select the maximum number of activities that don't overlap.
The problem is typically solved by selecting the activity that finishes the earliest and then selecting
the next activity that starts after the current one finishes.
Greedy Strategy: Always select the next activity that finishes first, and discard any overlapping
activities.
Algorithm:
1. Sort activities by their finish times.
2. Select the first activity.
3. For each subsequent activity, if the start time is greater than or equal to the finish time of the
previous activity, select it.
Time Complexity: Sorting the activities takes O(nlogn), where n is the number of activities.
Python Example:
python
Copy code
def activity_selection(start_times, finish_times):
n = len(start_times)
activities = list(zip(start_times, finish_times))
activities.sort(key=lambda x: x[1])

selected_activities = [activities[0]]
last_finish_time = activities[0][1]

for i in range(1, n):


if activities[i][0] >= last_finish_time:
selected_activities.append(activities[i])
last_finish_time = activities[i][1]
return selected_activities
4.4 Prim's and Kruskal's Algorithms (Minimum Spanning Tree)
Both Prim's and Kruskal's algorithms are greedy algorithms used to find a minimum spanning tree
(MST) in a connected, weighted graph. A minimum spanning tree connects all the vertices with the
minimum possible total edge weight.
• Prim’s Algorithm: Starts with an arbitrary vertex and adds the minimum weight edge to the
growing spanning tree.
• Kruskal’s Algorithm: Sorts all edges in the graph and adds the smallest edge to the MST,
provided it doesn't form a cycle.
Prim’s Algorithm:
1. Start with any node and add edges to the tree based on the minimum weight edge connecting
a new node.
2. Repeat until all nodes are included in the MST.
Kruskal’s Algorithm:
1. Sort all edges by weight.
2. Add edges to the MST from smallest to largest weight, skipping edges that would create a
cycle.
Time Complexity: O(ElogV) for Prim’s algorithm with a priority queue, and O(ElogE) for
Kruskal’s algorithm.

5. Advantages and Disadvantages of Greedy Algorithms


Advantages:
• Efficiency: Greedy algorithms are typically fast and have lower time complexities compared
to other algorithms like dynamic programming.
• Simplicity: They are easy to implement and understand.
• Useful in Certain Problems: In problems where the greedy approach is applicable, it offers
optimal solutions quickly.

Disadvantages:
• Non-optimal Solutions: Greedy algorithms do not always produce the optimal solution,
especially in problems where optimal substructure does not hold.
• Limited Application: Not all problems can be solved optimally with greedy algorithms.

6. Conclusion
Greedy algorithms are powerful and efficient in solving certain types of problems, especially those
with optimal substructure and greedy-choice properties. However, their applicability is limited, and
they do not always guarantee the best solution. Understanding when and where to use greedy
algorithms is crucial in algorithm design and problem-solving.

You might also like