Skip to content

Commit 901ff82

Browse files
Merge branch 'CodeHarborHub:main' into sivaprasath-closes-issue-1892
2 parents 92695c3 + 3fe121a commit 901ff82

File tree

6 files changed

+371
-0
lines changed

6 files changed

+371
-0
lines changed

docs/dsa/algorithms/Greedy.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
id: greedy-in-dsa
3+
title: Greedy Algorithm in Data Structures and Algorithms
4+
sidebar_label: Greedy Algorithm
5+
sidebar_position: 6
6+
description: ""
7+
tags:
8+
[dsa,data-algorithms , Greedy
9+
]
10+
---
11+
12+
The Greedy algorithm is a simple and intuitive approach used to solve optimization problems. It follows the greedy principle of making locally optimal choices at each step to find a global optimum solution.
13+
![alt text](image-6.png)
14+
15+
To implement a Greedy algorithm, follow these steps:
16+
17+
1. Understand the problem: Identify the objective or goal you want to achieve.
18+
19+
2. Define the problem as subproblems: Break down the problem into smaller, independent subproblems.
20+
21+
3. Determine the greedy choice: Make a locally optimal choice at each step that leads to the overall optimal solution.
22+
23+
4. Verify feasibility: Check if the chosen option satisfies constraints and requirements.
24+
25+
5. Update the solution: Include the chosen option in the current solution.
26+
27+
6. Repeat steps 3-5: Continue making greedy choices until the problem is solved or the desired solution is obtained.
28+
29+
30+
### Types of Greedy Algorithms
31+
32+
1. Activity Selection: This algorithm selects a maximum number of compatible activities that can be performed in a given time frame. It prioritizes activities based on their finish times or other criteria.
33+
34+
2. Fractional Knapsack: This algorithm solves the fractional knapsack problem, where items can be divided into fractions. It selects items based on their value-to-weight ratio, maximizing the total value while considering the capacity constraint.
35+
36+
3. Huffman Coding: This algorithm is used for data compression. It assigns variable-length codes to characters based on their frequency of occurrence, with more frequent characters having shorter codes.
37+
38+
4. Dijkstra's Algorithm: This algorithm finds the shortest path in a weighted graph from a source vertex to all other vertices. It selects the vertex with the minimum distance at each step, gradually expanding the shortest path tree.
39+
40+
5. Prim's Algorithm: This algorithm finds the minimum spanning tree of a connected weighted graph. It starts with an arbitrary vertex and greedily adds the edge with the minimum weight that connects the current tree to a new vertex.
41+
42+
6. Kruskal's Algorithm: This algorithm also finds the minimum spanning tree of a connected weighted graph. It sorts the edges in non-decreasing order of their weights and greedily adds the edges that do not form a cycle.
43+
44+
7. Coin Change: This algorithm solves the problem of making change for a given amount using the fewest number of coins. It selects the largest denomination coins first until the desired amount is reached.
45+
46+
8. Interval Scheduling: This algorithm schedules a maximum number of tasks with overlapping intervals. It selects tasks based on their finish times or other criteria, maximizing the number of non-overlapping tasks.
47+
48+
These are just a few examples of greedy algorithms. Each algorithm has its own specific problem-solving approach, but they all share the common characteristic of making locally optimal choices at each step to achieve a global optimum solution.
49+
50+
51+
### Advantages of the Greedy algorithm:
52+
53+
- Simplicity: Easy to understand and implement compared to complex algorithms.
54+
- Efficiency: Provides fast and efficient solutions in many cases.
55+
- Intuitive: Follows a natural and intuitive thought process.
56+
57+
### Disadvantages of the Greedy algorithm:
58+
59+
- Lack of global optimization: Locally optimal choices may not always lead to the globally optimal solution.
60+
- Suboptimal choices: Locally optimal choices may not result in the best overall solution.
61+
- Limited applicability: Not suitable for all problems, especially those requiring a comprehensive approach.
62+
63+
Note that the Greedy algorithm may not always be the best choice. Analyze the problem and consider other approaches for the most efficient solution.
64+
65+
**Here's an example code using the Greedy algorithm:**
66+
67+
```python
68+
def knapsack_greedy(values, weights, capacity):
69+
# Create a list of items with their values and weights
70+
items = list(zip(values, weights))
71+
72+
# Sort the items based on their value-to-weight ratio in descending order
73+
items.sort(key=lambda x: x[0] / x[1], reverse=True)
74+
75+
# Initialize the total value and total weight
76+
total_value = 0
77+
total_weight = 0
78+
79+
# Iterate through the sorted items
80+
for value, weight in items:
81+
# Check if adding the current item exceeds the capacity
82+
if total_weight + weight <= capacity:
83+
# Add the item to the knapsack
84+
total_value += value
85+
total_weight += weight
86+
87+
return total_value
88+
89+
# Example usage
90+
values = [60, 100, 120]
91+
weights = [10, 20, 30]
92+
capacity = 50
93+
94+
max_value = knapsack_greedy(values, weights, capacity)
95+
print("Maximum value:", max_value)
96+
```
97+
98+
This code demonstrates the Greedy algorithm in action by solving the Knapsack problem. The goal is to maximize the total value of items that can be put into a knapsack with a given capacity. The algorithm selects items based on their value-to-weight ratio, choosing the most valuable items first until the knapsack is full.
99+
100+
### Conclusion
101+
102+
The Greedy algorithm is a powerful and intuitive approach for solving optimization problems. It follows the principle of making locally optimal choices at each step to find a global optimum solution.
103+
104+
The advantages of the Greedy algorithm include its simplicity, efficiency, and intuitive thought process. It is easy to understand and implement compared to complex algorithms, provides fast and efficient solutions in many cases, and follows a natural thought process.
105+
106+
However, the Greedy algorithm also has its limitations. Locally optimal choices may not always lead to the globally optimal solution, resulting in suboptimal choices. It is not suitable for all problems, especially those requiring a comprehensive approach.
107+
108+
In conclusion, the Greedy algorithm is a valuable tool in solving optimization problems, but it is important to analyze the problem and consider other approaches for the most efficient solution.

docs/dsa/algorithms/image-5.png

393 KB
Loading

docs/dsa/algorithms/image-6.png

121 KB
Loading
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
id: filter-function
3+
title: Filter Function in Python
4+
sidebar_label: Filter Function
5+
---
6+
7+
## Definition
8+
9+
The filter function is a built-in Python function used for constructing an iterator from elements of an iterable for which a function returns true.
10+
11+
**Syntax**:
12+
13+
```python
14+
filter(function, iterable)
15+
```
16+
17+
**Parameters**:
18+
19+
- **function:** A function that tests if each element of an iterable returns True or False.
20+
- **iterable:** An iterable like sets, lists, tuples, etc., whose elements are to be filtered.
21+
- **Returns:** An iterator that is already filtered.
22+
23+
## Basic Usage
24+
25+
**Example 1: Filtering a List of Numbers**:
26+
27+
```python
28+
# Define a function that returns True for even numbers
29+
def is_even(n):
30+
return n % 2 == 0
31+
32+
numbers = [1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
33+
even_numbers = filter(is_even, numbers)
34+
35+
# Convert the filter object to a list
36+
print(list(even_numbers)) # Output: [2, 4, 6, 8, 10]
37+
```
38+
39+
**Example 2: Filtering with a Lambda Function**:
40+
41+
```python
42+
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
43+
odd_numbers = filter(lambda x: x % 2 != 0, numbers)
44+
45+
print(list(odd_numbers)) # Output: [1, 3, 5, 7, 9]
46+
```
47+
48+
**Example 3: Filtering Strings**:
49+
50+
```python
51+
words = ["apple", "banana", "cherry", "date", "elderberry", "fig", "grape" , "python"]
52+
long_words = filter(lambda word: len(word) > 5, words)
53+
54+
print(list(long_words)) # Output: ['banana', 'cherry', 'elderberry', 'python']
55+
```
56+
57+
## Advanced Usage
58+
59+
**Example 4: Filtering Objects with Attributes**:
60+
61+
```python
62+
class Person:
63+
def __init__(self, name, age):
64+
self.name = name
65+
self.age = age
66+
67+
people = [
68+
Person("Alice", 30),
69+
Person("Bob", 15),
70+
Person("Charlie", 25),
71+
Person("David", 35)
72+
]
73+
74+
adults = filter(lambda person: person.age >= 18, people)
75+
adult_names = map(lambda person: person.name, adults)
76+
77+
print(list(adult_names)) # Output: ['Alice', 'Charlie', 'David']
78+
```
79+
80+
**Example 5: Using None as the Function**:
81+
82+
```python
83+
numbers = [0, 1, 2, 3, 0, 4, 0, 5]
84+
non_zero_numbers = filter(None, numbers)
85+
86+
print(list(non_zero_numbers)) # Output: [1, 2, 3, 4, 5]
87+
```
88+
89+
**NOTE**: When None is passed as the function, filter removes all items that are false.
90+
91+
## Time Complexity:
92+
- The time complexity of filter() depends on two factors:
93+
1. The time complexity of the filtering function (the one you provide as an argument).
94+
2. The size of the iterable being filtered.
95+
- If the filtering function has a constant time complexity (e.g., $O(1)$), the overall time complexity of filter() is linear ($O(n)$), where ‘n’ is the number of elements in the iterable.
96+
97+
## Space Complexity:
98+
99+
- The space complexity of filter() is also influenced by the filtering function and the size of the iterable.
100+
- Since filter() returns an iterator, it doesn’t create a new list in memory. Instead, it generates filtered elements on-the-fly as you iterate over it. Therefore, the space complexity is $O(1)$.
101+
102+
## Conclusion:
103+
104+
Python’s filter() allows you to perform filtering operations on iterables. This kind of operation
105+
consists of applying a Boolean function to the items in an iterable and keeping only those values
106+
for which the function returns a true result. In general, you can use filter() to process existing
107+
iterables and produce new iterables containing the values that you currently need.Both versions of
108+
Python support filter(), but Python 3’s approach is more memory-efficient due to the use of
109+
iterators.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
id: map-function
3+
title: Map Function in Python
4+
sidebar_label: Map Function
5+
---
6+
7+
The `map()` function in Python is a built-in function used for applying a given function to each
8+
item of an iterable (like a list, tuple, or dictionary) and returning a new iterable with the
9+
results. It's a powerful tool for transforming data without the need for explicit loops. Let's break
10+
down its syntax, explore examples, and discuss various use cases.
11+
12+
### Syntax:
13+
14+
```python
15+
map(function, iterable1, iterable2, ...)
16+
```
17+
18+
- `function`: The function to apply to each item in the iterables.
19+
- `iterable1`, `iterable2`, ...: One or more iterable objects whose items will be passed as
20+
arguments to `function`.
21+
22+
### Examples:
23+
24+
#### Example 1: Doubling the values in a list
25+
26+
```python
27+
# Define the function
28+
def double(x):
29+
return x * 2
30+
31+
# Apply the function to each item in the list using map
32+
original_list = [1, 2, 3, 4, 5]
33+
doubled_list = list(map(double, original_list))
34+
print(doubled_list) # Output: [2, 4, 6, 8, 10]
35+
```
36+
37+
#### Example 2: Converting temperatures from Celsius to Fahrenheit
38+
39+
```python
40+
# Define the function
41+
def celsius_to_fahrenheit(celsius):
42+
return (celsius * 9/5) + 32
43+
44+
# Apply the function to each Celsius temperature using map
45+
celsius_temperatures = [0, 10, 20, 30, 40]
46+
fahrenheit_temperatures = list(map(celsius_to_fahrenheit, celsius_temperatures))
47+
print(fahrenheit_temperatures) # Output: [32.0, 50.0, 68.0, 86.0, 104.0]
48+
```
49+
50+
### Use Cases:
51+
52+
1. **Data Transformation**: When you need to apply a function to each item of a collection and
53+
obtain the transformed values, `map()` is very handy.
54+
55+
2. **Parallel Processing**: In some cases, `map()` can be utilized in parallel processing scenarios,
56+
especially when combined with `multiprocessing` or `concurrent.futures`.
57+
58+
3. **Cleaning and Formatting Data**: It's often used in data processing pipelines for tasks like
59+
converting data types, normalizing values, or applying formatting functions.
60+
61+
4. **Functional Programming**: In functional programming paradigms, `map()` is frequently used along
62+
with other functional constructs like `filter()` and `reduce()` for concise and expressive code.
63+
64+
5. **Generating Multiple Outputs**: You can use `map()` to generate multiple outputs simultaneously
65+
by passing multiple iterables. The function will be applied to corresponding items in the iterables.
66+
67+
6. **Lazy Evaluation**: In Python 3, `map()` returns an iterator rather than a list. This means it's
68+
memory efficient and can handle large datasets without loading everything into memory at once.
69+
70+
Remember, while `map()` is powerful, it's essential to balance its use with readability and clarity.
71+
Sometimes, a simple loop might be more understandable than a `map()` call.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
id: reduce-function
3+
title: Reduce Function in Python
4+
sidebar_label: Reduce Function
5+
---
6+
7+
## Definition:
8+
The reduce() function is part of the functools module and is used to apply a binary function (a
9+
function that takes two arguments) cumulatively to the items of an iterable (e.g., a list, tuple, or
10+
string). It reduces the iterable to a single value by successively combining elements.
11+
12+
**Syntax**:
13+
```python
14+
from functools import reduce
15+
reduce(function, iterable, initial=None)
16+
```
17+
**Parameters**:<br />
18+
*function* : The binary function to apply. It takes two arguments and returns a single value.<br />
19+
*iterable* : The sequence of elements to process.<br />
20+
*initial (optional)*: An initial value. If provided, the function is applied to the initial value
21+
and the first element of the iterable. Otherwise, the first two elements are used as the initial
22+
values.
23+
24+
## Working:
25+
- Intially , first two elements of iterable are picked and the result is obtained.
26+
- Next step is to apply the same function to the previously attained result and the number just
27+
succeeding the second element and the result is again stored.
28+
- This process continues till no more elements are left in the container.
29+
- The final returned result is returned and printed on console.
30+
31+
## Examples:
32+
33+
**Example 1:**
34+
```python
35+
numbers = [1, 2, 3, 4, 10]
36+
total = reduce(lambda x, y: x + y, numbers)
37+
print(total) # Output: 20
38+
```
39+
**Example 2:**
40+
```python
41+
numbers = [11, 7, 8, 20, 1]
42+
max_value = reduce(lambda x, y: x if x > y else y, numbers)
43+
print(max_value) # Output: 20
44+
```
45+
**Example 3:**
46+
```python
47+
# Importing reduce function from functools
48+
from functools import reduce
49+
50+
# Creating a list
51+
my_list = [10, 20, 30, 40, 50]
52+
53+
# Calculating the product of the numbers in my_list
54+
# using reduce and lambda functions together
55+
product = reduce(lambda x, y: x * y, my_list)
56+
57+
# Printing output
58+
print(f"Product = {product}") # Output : Product = 12000000
59+
```
60+
61+
## Difference Between reduce() and accumulate():
62+
- **Behavior:**
63+
- reduce() stores intermediate results and only returns the final summation value.
64+
- accumulate() returns an iterator containing all intermediate results. The last value in the
65+
iterator is the summation value of the list.
66+
67+
- **Use Cases:**
68+
- Use reduce() when you need a single result (e.g., total sum, product) from the iterable.
69+
- Use accumulate() when you want to access intermediate results during the reduction process.
70+
71+
- **Initial Value:**
72+
- reduce() allows an optional initial value.
73+
- accumulate() also accepts an optional initial value since Python 3.8.
74+
75+
- **Order of Arguments:**
76+
- reduce() takes the function first, followed by the iterable.
77+
- accumulate() takes the iterable first, followed by the function.
78+
79+
## Conclusion:
80+
Python's Reduce function enables us to apply reduction operations to iterables using lambda and call
81+
able functions. A function called reduce() reduces the elements of an iterable to a single
82+
cumulative value. The reduce function in Python solves various straightforward issues, including
83+
adding and multiplying iterables of numbers.

0 commit comments

Comments
 (0)