Module4Notes
Module4Notes
-----------------------------------------------------------
----------------------------------------------
Brute-force Approach
1. Padlock
Imagine you encounter a padlock with a four-digit numeric code. The brute-
force approach would involve sequentially trying every possible
combination from ”0000” to ”9999” until the correct code unlocks the
padlock.
4. Sudoku Solving
---------------------------------------------------------------------------
1. Divide: Split the original problem into smaller sub-problems that are
easier to solve. The sub-problems should be similar to the original problem.
Once the files are divided into smaller subsets, each subset is organized
recursively. For example, you could sort documents into subcategories
such as reports, presentations, and spreadsheets. Each of these
categories might be further divided into subfolders based on date or
project. This recursive approach allows you to systematically manage and
categorize each subset. For very small subsets, such as a single folder with
a few files, a direct solution is applied without further division, making the
problem- solving process more manageable.
begin
if (SMALL (P))
then return S (p)
else
divide p into smaller instances p1, p2, …. Pk, k > 1
apply DANDC to each of these sub problems;
return (COMBINE (DANDC (p1) , DANDC (p2),….,
DANDC (pk));
endif
end
The core idea is to split the array into two halves, sort each half, and
then merge them back together.
3. Combine: Merge the two sorted halves to produce the sorted array.
1. Function mergeSort()
Check if the array has one or zero elements. If true, return the array as it
is already sorted.Otherwise, find the middle index of the array.
Split the array into two halves: from the beginning to the middle andfrom
the middle+1 to the end.
Recursively apply mergeSort() to the first half and the second half
Function merge()
Create an empty list called sorted_arr to store the sorted elements.
While both halves have elements:
Compare the first element of the left half with the first
element of the right half.
Remove the smaller element and append it to the
sorted_arr list.
End while
If the left half still has elements, append them all to the sorted_arr
list.
If the right half still has elements, append them all to the
sorted_arrlist.
Return the sorted_arr list, which now contains the sorted elements
from both halves
1.Optimal substructure
2.Overlapping subproblems.
Example. Shortest Path in a Grid: Imagine you need to find the shortest
path from the top-left corner to the bottom-right corner of a grid. You can
only move right or down. Each cell in the grid has a certain cost associated
with entering it, and your goal is to minimize the total cost of the path.
3 2
1 4 5 (i-1,j)
3 2 (i,j-1) 4(i,j)
For example,
To find Fibonacci(5), you need the values of Fibonacci(4) and Fibonacci(3).
To compute Fibonacci(4), you need Fibonacci(3) and Fibonacci(2).
Notice that Fibonacci(3) is computed multiple times when calculating
different Fibonacci numbers.
Greedy Solution
1.Sort the coin denominations in descending order.
2. Start with the highest denomination and take as many coins of that
denomination as possible without exceeding the amount.
3. Repeat the process with the next highest denomination until the
amount is made up.
Example
Suppose you have coin denominations of 1, 5, 10, and 25 Rupees,
and you need to make change for 63 Rupees.
1. Take two 25-Rupee coins (63 - 50 = 13 Rupees left).
2. Take one 10-Rupee coin (13 - 10 = 3 Rupees left).
3. Take three 1-Rupee coins (3 - 3 = 0 Rupee left).
Thus, the minimum number of coins needed is six (two 25-Rupee
coins, one 10-Rupee coin, and three 1-Rupee coins).
2. Iterate through the sorted list of tasks and keep track of the
total time and count of tasks completed: For each task, if adding
the task’s completion time to the total time does not exceed the
available time, add the task to the count and update the total time.
completion_times = [2, 3, 1, 4, 6]
available_time = 8
print(f"Maximum number of tasks that can be completed:”
,max_tasks(completion_times, available_time))
Algorithmic Solution:
1. Initialize Variables:
TotalJeansBought=0
CouponsCollected={ }:
N=The total number of different coupon types
2. Buying Process:
Loop Until All Coupons Are Collected:
Total Jeans Bought +=1 Each time you buy a pair of jeans,
increase the counter for the total
jeans bought by one.
coupon = random.randint(1, n)
CouponsCollected= CouponsCollected.add(coupon)
When you buy a pair of jeans, you get
a coupon. Add this coupon to your set
of collected coupons.
Check if you have collected all N different types of coupons by
comparing the size of your set to N.
3. Repeat for Accuracy:
To get a reliable estimate, repeat the entire buying process many
times (e.g., 100,000 times).
Keep a running total of the number of jeans bought across all
these repetitions.
4. Calculate the Average:
Average= Total Jeans Bought/100,000
After completing all repetitions, calculate the average number of
jeans bought by dividing the total number of jeans bought by the
number of repetitions.
5. Output the Result:
The average number of jeans bought from the repeated
simulations gives you a good estimate of how many pairs of jeans
you would typically need to buy before collecting all n coupons and
getting a free pair.
Algorithmic Solution:
1. Initialization:
• Set up variables to count the total number of correct matches
across all simulations.
• Define the number of simulations to ensure statistical reliability.
• Define the number of people n.
2. Simulate the Process:
For each simulation:
– Create a list of hats representing each person.
– Shuffle the list to simulate random distribution.
– Count how many people receive their own hat.
– Add this count to the total number of correct matches.
3. Calculate the Expected Value:
Divide the total number of correct matches by the number of
simulations to get the average.
4. Output the Result:
Print the expected number of people who get their own hats back.
Motivations for the Randomized Approach