mirror of
https://github.com/lavafroth/lavafroth.github.io.git
synced 2026-05-28 09:31:17 -03:00
feat: remove secret posts
This commit is contained in:
@@ -1,467 +0,0 @@
|
||||
---
|
||||
title: "for seshu baby mwa mwa"
|
||||
date: 2025-10-03T16:04:18+05:30
|
||||
draft: false
|
||||
---
|
||||
|
||||
> Update: I have added the GA 2 sols as well. Please take them with a grain of salt obviously
|
||||
I am also fallible to mistakes.
|
||||
|
||||
# AQ2.1
|
||||
1. \( O(n^2) \)
|
||||
2. \( O(n\ log\ n) \)
|
||||
3. \( O(n^3) \)
|
||||
4. \( O(n + log\ m) \)
|
||||
5. \( O(log\ n) \)
|
||||
6. \( O(n^2\ log\ n) \)
|
||||
|
||||
# AQ2.2
|
||||
|
||||
1. \( O(log\ n) \)
|
||||
2. 5
|
||||
3. 3
|
||||
4. 3
|
||||
5. 2
|
||||
6. Multiple options:
|
||||
- It works only on sorted arrays.
|
||||
- It has a best-case time complexity of O(1).
|
||||
|
||||
# AQ2.3
|
||||
|
||||
> Selection sort always makes n(n-1)/2 comparisons which is of order \( O(n^2) \)
|
||||
|
||||
1. 3
|
||||
2. 15
|
||||
3. 45
|
||||
4. Multiple options:
|
||||
- [4, 4, 3, 5, 6]
|
||||
- [7, 2, 8, 7, 3]
|
||||
- [9, 1, 4, 9, 5]
|
||||
5. Multiple options:
|
||||
- It is an in-place algorithm.
|
||||
- It performs \( O(n^2) \) comparisons in the worst case.
|
||||
6. \( \lceil{n/2}\rceil \) In this case, you narrow the window of comparison on both sides by 1
|
||||
|
||||
# AQ2.4
|
||||
|
||||
1. 7
|
||||
|
||||
Original | Shift
|
||||
---------|-------
|
||||
[8, 5, 2, 9, 1] | 4 shifts
|
||||
[1, 8, 5, 2, 9] | 2 shifts
|
||||
[1, 2, 8, 5, 9] | 1 shift
|
||||
[1, 2, 5, 8, 9]
|
||||
|
||||
Total 7
|
||||
|
||||
2. 6
|
||||
|
||||
Original | Shift
|
||||
---------|-------
|
||||
[4, 3, 2, 1] | 3 shifts
|
||||
[1, 4, 3, 2] | 2 shifts
|
||||
[1, 2, 4, 3] | 1 shift
|
||||
[1, 2, 3, 4]
|
||||
|
||||
Total 6
|
||||
|
||||
3. 0
|
||||
4. 10
|
||||
5. 10
|
||||
6. `array[j] > key → array[j] < key`
|
||||
7. \( O(n) \)
|
||||
|
||||
# AQ2.5
|
||||
|
||||
> Merging two sorted lists of size \(m\) and \(n\) takes worst case \(m + n - 1\) comparisons
|
||||
|
||||
1. 14
|
||||
2. To combine two sorted sublists into a single sorted list.
|
||||
3. Multiple options:
|
||||
- It is a divide-and-conquer algorithm
|
||||
- It requires additional space proportional to the size of the input list.
|
||||
- It is stable.
|
||||
4. 4
|
||||
5. \(T(n) = 2T(n/2) + n\)
|
||||
6. 6
|
||||
7. Merge Sort has the same time complexity \( O(n\ log\ n) \) for best, worst, and average cases.
|
||||
8. 133
|
||||
9. 89
|
||||
10. 275
|
||||
|
||||
# GA 2
|
||||
|
||||
### 1. What is the time complexity of the function?
|
||||
|
||||
```python
|
||||
def fun(n):
|
||||
total = 0
|
||||
for i in range(n):
|
||||
total += i
|
||||
|
||||
k=0
|
||||
for i in range(n):
|
||||
for j in range(n):
|
||||
k += i * j
|
||||
for l in range(5):
|
||||
k=1
|
||||
|
||||
for i in range(1000):
|
||||
total -= 1
|
||||
return total + k
|
||||
```
|
||||
|
||||
The second block with nested loops is the bottleneck, it has two loops, implying \( O(n \times n) = O(n^2) \).
|
||||
The other loops are linear \( O(n) \) and only this second block will dominate. The answer is the dominating term.
|
||||
|
||||
\( O(n^2) \)
|
||||
|
||||
---
|
||||
|
||||
### 2. What is the time complexity of the function?
|
||||
|
||||
```python
|
||||
def func(n):
|
||||
s=0
|
||||
if n <= 0:
|
||||
return 0
|
||||
for i in range(n):
|
||||
j= 0
|
||||
while j * j <n:
|
||||
s += j
|
||||
j += 1
|
||||
return s
|
||||
```
|
||||
|
||||
The outer loop goes `for` \(n\) times. The inner loop runs as long as the iterator satisfies
|
||||
$$ j \times j \le n $$
|
||||
which can be rewritten as
|
||||
$$ j \le \sqrt n $$
|
||||
|
||||
Thus, the number of operations after nesting the two loops is
|
||||
$$ O(n \sqrt n) $$
|
||||
|
||||
---
|
||||
|
||||
### 3. Let \(T_{best}(n),T_{avg}(n),T_{worst}(n)\) be the best-case, average-case, and worst-case running times of an algorithm, respectively, executed on an input of size \(n\). Select the correct statements.
|
||||
|
||||
Rule of thumb: \(T_{best}(n) \le T_{avg}(n) \le T_{worst}(n)\)
|
||||
|
||||
In plain words: When the algorithm gets lucky with an easy input, which is the best case \(T_{best}(n)\), the time it takes is obviously less than the average case \(T_{avg}(n)\).
|
||||
Similarly, \(T_{avg}(n) \le T_{worst}(n)\).
|
||||
|
||||
Now let's see the correct options.
|
||||
|
||||
#### \(T_{best}(n) = O(T_{avg}(n))\)
|
||||
|
||||
Big O notation means the upper bound. The time taken for the best case is upper bounded by the time taken by the average case.
|
||||
|
||||
#### \(T_{worst}(n) = \Omega(T_{avg}(n))\)
|
||||
|
||||
\(\Omega\) notation means the lower bound. The time taken for the worst case is lower bounded by the time taken by the average case.
|
||||
|
||||
### If \(T_{best}(n) = \Theta(n^2)\) and \(T_{worst}(n) = \Theta(n^2)\), then \(T_{avg}(n) = \Theta(n^2)\)
|
||||
|
||||
If the best and worst cases are tightly bound,
|
||||
> Remember, \(\Theta\) notation is the sandwich between O and \(\Omega\) bounds
|
||||
|
||||
then the average case is also sandwiched in between by the same tight bound.
|
||||
|
||||
---
|
||||
|
||||
### 4. How many effective swaps are performed by selection sort on `[5, 2, 8, 2, 4]`?
|
||||
|
||||
Look, I did this with python because I was feeling lazy, you can do it in your head or on paper as well. Sorri baby, I was tired.
|
||||
|
||||
Answer is 3.
|
||||
|
||||
---
|
||||
|
||||
### 5. Select correct statements about the given insertion sort implementation.
|
||||
|
||||
- The sort is stable and it sorts in-place
|
||||
- After m iterations of the for-loop, the first m elements in the list are in sorted order
|
||||
|
||||
---
|
||||
|
||||
### 6. You are implementing binary search on a sorted array that may contain duplicate values of the target element X . You need to find the index of the last occurrence of X. If an instance of X is found at L[mid], how should the search proceed to find the last possible occurence.
|
||||
|
||||
Store mid as a potential answer and continue searching in the right subarray by setting low = mid + 1 .
|
||||
|
||||
---
|
||||
|
||||
### 7. A school wants to maintain a database of its students. Each student has a unique id and it is stored along with other details. Adding a new student with a unique id, searching for a student using their id, and removal of students are the frequent operations performed on the database. From the options given below, choose the most efficient technique to store the data.
|
||||
|
||||
Maintain a sorted list with id. Whenever a new student is added, insert the student details into the respective position in the sorted list by id.
|
||||
|
||||
---
|
||||
|
||||
### 8. Find the time complexity of the function:
|
||||
|
||||
```python
|
||||
def tsearch(L, x):
|
||||
global c
|
||||
c += 1
|
||||
n = len(L)
|
||||
|
||||
if n==0:
|
||||
return False
|
||||
|
||||
if L[n // 3] == x:
|
||||
return True
|
||||
|
||||
if L[2 * n // 3] == x:
|
||||
return True
|
||||
|
||||
if x < L[n // 3]:
|
||||
return tsearch(L[:n // 3], x)
|
||||
elif x > L[2 * n // 3]:
|
||||
return tsearch(L[2 * n // 3:], x)
|
||||
else:
|
||||
return tsearch(L[n // 3 : 2 * n// 3], x)
|
||||
```
|
||||
|
||||
This is basically a spin on the binary search algorithm except that instead of dividing the search space into half every time, you are dividing it by 3.
|
||||
|
||||
All such divide-and-conquer algorithms take \(O(log\ n)\) time.
|
||||
|
||||
---
|
||||
|
||||
### 9. Arrange the following functions in increasing order of asymptotic complexity.
|
||||
|
||||
$$
|
||||
\begin{aligned}
|
||||
f_1(n) = 3n + log(n)\\
|
||||
f_2(n) = log(n)^2\\
|
||||
f_3(n) = log(log(n))\\
|
||||
f_4(n) = 100log(n)\\
|
||||
f_5(n) = 3n\ log(n)
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
Here, \(f_3(n) = log(log(n))\) grows very very slowly.
|
||||
|
||||
between the next \(f_4(n) = 100log(n)\) and \(f_5(n) = 3n\ log(n)\)
|
||||
|
||||
|
||||
$$ f_3(n) < f_4(n) < f_2(n) < f_1(n) < f_5(n) $$
|
||||
|
||||
---
|
||||
|
||||
### 10. Correct relationship of function growths
|
||||
|
||||
$$
|
||||
f(n) = \Omega(g(n)),\ g(n) = O(h(n))
|
||||
$$
|
||||
|
||||
---
|
||||
|
||||
### 11. Recursively check the midpoints for this one.
|
||||
|
||||
94, 150, 99
|
||||
|
||||
---
|
||||
|
||||
### 12. What will be the number of swaps that the following Insertion sort?
|
||||
|
||||
insertion sort considers the first chunck of the array to be sorted, finds the smallest element beyond this chunk
|
||||
and inserts it (or bubbles it up as I like to think of it) into the pre sorted chunk.
|
||||
|
||||
Initially, this chunk is of size 1 because 1 element is sorted by definition.
|
||||
|
||||
Original: `[38, 28, 43, 22, 112, 33, 39]`
|
||||
|
||||
Original | Swaps | Element that bubbled up
|
||||
---|---|---
|
||||
[28, 38, 43, 22, 112, 33, 39] | 1 | 38
|
||||
[22, 28, 38, 43, 112, 33, 39] | 3 | 22
|
||||
[22, 28, 33, 38, 43, 112, 39] | 3 | 33
|
||||
[22, 28, 33, 38, 39, 43, 112] | 2 | 39
|
||||
|
||||
Total swaps: 9
|
||||
|
||||
### 13. Stable sort `[(8, 1), (7, 5), (6, 1), (2, 5), (5, 2), (9, 0)]` according to the y value of (x, y) pairs.
|
||||
|
||||
Stable sort means the order of equally valued objects is not perturbed. If both of us have equal grades in a subject,
|
||||
and in the score list your name is before mine, it should stay that way after sorting.
|
||||
|
||||
`[(9, 0), (8, 1), (6, 1), (5, 2), (7, 5), (2, 5)]`
|
||||
|
||||
### 14. Perform two way merge, how many comparisons?
|
||||
all of the elements of L1 come before L2. This means there will be \(min(len(L1), len(L2))\) comparisons.
|
||||
$$ min(len(L1), len(L2)) = 3 $$
|
||||
|
||||
L3 and L4 have interleaving elements. This is the worst case where the number of comparisons is
|
||||
|
||||
$$
|
||||
\begin{aligned}
|
||||
m + n - 1\\
|
||||
= 3 + 3 - 1 = 5
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
For the two new lists, all elements of
|
||||
|
||||
`[1,2,3,4,5,6]`
|
||||
|
||||
come before elements of
|
||||
|
||||
`[7,8,9,10,11,12]`
|
||||
|
||||
$$ min(len(L1), len(L2)) = 6 $$
|
||||
|
||||
Total = 6 + 5 + 3 = 14
|
||||
|
||||
# GRPAs
|
||||
|
||||
### 1. String sorting question
|
||||
This has two parts:
|
||||
- Sort with respect to starting letters.
|
||||
- Sort with respect to starting letters, then for each block of common letters, sort the trailing numbers in descending order.
|
||||
|
||||
Here's the trick to solve the second part, you always sort fields in the reverse order of what they ask for.
|
||||
So first sort by numbers in descending order, then sort by the starting letters.
|
||||
|
||||
Sorri this solution is bit big. You could also use the built in `sorted` function in python without implementing
|
||||
merge sort like I did here.
|
||||
|
||||
```python
|
||||
def combinationSort(strList):
|
||||
by_first_letter = lambda v: ord(v[0])
|
||||
by_last_digits = lambda v: int(v[1:])
|
||||
sorted_0 = mergesort(strList, by_first_letter)
|
||||
|
||||
sorted_1 = mergesort(strList, by_last_digits, ascending=False)
|
||||
sorted_1 = mergesort(sorted_1, by_first_letter)
|
||||
return sorted_0, sorted_1
|
||||
|
||||
|
||||
def merge(a, b, by, ascending=True):
|
||||
i, j = 0, 0
|
||||
m, n = len(a), len(b)
|
||||
c = []
|
||||
while i + j != m + n:
|
||||
if i == m:
|
||||
return c + b[j:]
|
||||
if j == n:
|
||||
return c + a[i:]
|
||||
|
||||
a_ = a[i]
|
||||
b_ = b[j]
|
||||
# this XOR will flip the comparison
|
||||
if ascending ^ (by(a_) > by(b_)):
|
||||
i += 1
|
||||
c.append(a_)
|
||||
else:
|
||||
j += 1
|
||||
c.append(b_)
|
||||
return c
|
||||
|
||||
|
||||
def mergesort(v, by, ascending=True):
|
||||
n = len(v)
|
||||
if n == 1:
|
||||
return v
|
||||
|
||||
l = mergesort(v[: n // 2], by, ascending)
|
||||
r = mergesort(v[n // 2 :], by, ascending)
|
||||
return merge(l, r, by, ascending)
|
||||
```
|
||||
|
||||
### 2. Given an ascending list is rotated, find the biggest element.
|
||||
|
||||
{{< collapsable-explanation >}}
|
||||
|
||||
We will do a binary search. to calculate the midpoint, we need to know the start and the end indices.
|
||||
I call them head and tail respectively.
|
||||
|
||||
```python
|
||||
def findLargest(array):
|
||||
head, tail = 0, len(array) - 1
|
||||
```
|
||||
|
||||
If we want the largest element, it will be found in a slice of the array that is sorted in ascending order.
|
||||
We check that as the loop condition.
|
||||
|
||||
```python
|
||||
while array[head] > array[tail]:
|
||||
```
|
||||
|
||||
Calculate the midpoint every iteration.
|
||||
|
||||
```python
|
||||
mid = (head + tail) // 2
|
||||
```
|
||||
|
||||
If the middle element is greater than the last element, it might look like this:
|
||||
|
||||
```python
|
||||
if array[mid] > array[tail]:
|
||||
head = mid
|
||||
```
|
||||
|
||||

|
||||
|
||||
Observe that the left half of the midpoint is useless in this case. Therefore, we set the new head to the midpoint.
|
||||
|
||||
```python
|
||||
else:
|
||||
tail = mid - 1
|
||||
```
|
||||
|
||||
The opposite case might look like this:
|
||||
|
||||

|
||||
|
||||
In such a case, the midpoint along with anything to its right is useless. We throw that part away by reassigning tail to mid - 1.
|
||||
|
||||
Finally we return the last (standing) array element.
|
||||
|
||||
```python
|
||||
return array[tail]
|
||||
```
|
||||
|
||||
```python
|
||||
def findLargest(array):
|
||||
head, tail = 0, len(array) - 1
|
||||
while array[head] > array[tail]:
|
||||
mid = (head + tail) // 2
|
||||
if array[mid] > array[tail]:
|
||||
head = mid
|
||||
else:
|
||||
tail = mid - 1
|
||||
return array[tail]
|
||||
```
|
||||
|
||||
{{</ collapsable-explanation >}}
|
||||
|
||||
### 3. Perform merge on two lists via swaps only
|
||||
|
||||
The swap function works as `list_a.swap(index_a, list_b, index_b)` which is part of their custom implementation.
|
||||
|
||||
The trick is to treat A and B as a contiguous array: A + B
|
||||
|
||||
Any index `i` smaller than `len(A)` will index into A, anything bigger will index into B at offset `i-len(A)`.
|
||||
|
||||
The index function returns which array the current contiguous indexer indexes into and at what offset.
|
||||
|
||||
The rest of the `mergeInPlace` function body performs selection sort.
|
||||
|
||||
```python
|
||||
def index(A, B, x):
|
||||
return (A, x) if x < len(A) else (B, x - len(A))
|
||||
|
||||
def swap(A, B, x, y):
|
||||
source, source_offset = index(A, B, x)
|
||||
target, target_offset = index(A, B, y)
|
||||
source.swap(source_offset, target, target_offset)
|
||||
|
||||
def mergeInPlace(A, B):
|
||||
value_at = lambda x: A[x] if x < len(A) else B[x - len(A)]
|
||||
|
||||
size = len(A) + len(B)
|
||||
for i in range(size-1):
|
||||
smallest_index = min(range(i, size), key=value_at)
|
||||
swap(A, B, i, smallest_index)
|
||||
```
|
||||
@@ -1,480 +0,0 @@
|
||||
---
|
||||
title: "secret note jfgp3d7rrx0"
|
||||
date: 2025-10-28T16:09:00+05:30
|
||||
draft: false
|
||||
---
|
||||
|
||||
There will be an explanation for non-trivial questions.
|
||||
|
||||
# Activity 1
|
||||
|
||||
## 1
|
||||
|
||||
Dijkstra's algorithm guarantees finding the shortest path from a single source to all other vertices under which of the following conditions?
|
||||
|
||||
**Answer:** All edge weights must be non-negative.
|
||||
|
||||
## 2
|
||||
|
||||
|
||||
Consider an undirected graph with 5 vertices $(V_0, V_1, V_2, V_3, V_4)$. At a certain point
|
||||
in Dijkstra's algorithm (starting from $V_0$), the current tentative distances are:
|
||||
$dist = \{V_0:0, V_1:5, V_2:3, V_3:8, V_4:10\}$. And the processed set is: $\{V_0:True,
|
||||
V_1:False, V_2:False, V_3:False, V_4:False\}$. Assuming the next step is to select an unvisited
|
||||
vertex to mark as processed, which vertex will be chosen?
|
||||
|
||||
**Answer:** $V_2$
|
||||
|
||||
Explanation: Dijkstra will choose the next unprocessed vertex with the least weight.
|
||||
|
||||
## 3
|
||||
|
||||
Which of the following components is/are essential for a standard implementation of Dijkstra's algorithm?
|
||||
|
||||
**Answers:**
|
||||
|
||||
- A way to store the tentative shortest distance to each vertex.
|
||||
- A set to keep track of vertices whose shortest paths have been finalized.
|
||||
- A mechanism to select the unvisited vertex with the smallest current distance.
|
||||
|
||||
## 4
|
||||
|
||||
Consider an undirected graph with vertices S, A, B, C, D and edges with weights: S-A (4), S-B (2), A-C (5), B-A (1), B-D (8), C-D (3). If Dijkstra's algorithm starts from vertex 'S', what is the value of dist[D] immediately after vertex 'A' has been marked as processed?
|
||||
|
||||
**Answer:** 10
|
||||
|
||||
## 5
|
||||
|
||||
When Dijkstra's algorithm is examining an edge (u, v) from a newly processed vertex u , and it finds that the path source -> ... -> u -> v offers a shorter route to v than its currently recorded shortest distance ( dist[v] ), what is the direct consequence for dist[v] and v 's status?
|
||||
|
||||
**Answer:**
|
||||
dist[v] is updated, and v's status remains un-processed, awaiting its turn in a future selection step
|
||||
|
||||
## 6
|
||||
|
||||
Given a weighted graph where weights of all edges are unique, there is always a unique shortest path from a source to destination in such a graph.
|
||||
|
||||
**Answer:** False
|
||||
|
||||
Explanation: There can be multiple sequence of edges from vertex $A$ to $B$ representing the shortest path. The only necessary property is that the sum of the weights on these edges is the least.
|
||||
|
||||
# Activity 2
|
||||
|
||||
## 1
|
||||
|
||||
What is a fundamental capability of the Bellman-Ford algorithm that distinguishes it from Dijkstra's algorithm for finding shortest paths?
|
||||
|
||||
**Answer:** It is able to correctly find shortest paths in graphs containing negative edge weights.
|
||||
|
||||
## 2
|
||||
|
||||
For a graph with 7 vertices and 10 edges, if it contains no negative cycles, what is the minimum number of passes over all edges that the Bellman-Ford algorithm needs to perform to guarantee that all shortest path distances are finalized?
|
||||
|
||||
**Answer:** 6
|
||||
|
||||
## 3
|
||||
|
||||
Consider the following directed graph. If the Bellman-Ford algorithm starts from vertex 'S', what are the shortest distances to vertices 'A', 'B', and 'C' (in that order: dist[A] , dist[B] , dist[C] ) after exactly 2 passes over all edges?
|
||||
|
||||
**Answer:** 6
|
||||
|
||||
Explanation: It takes $n-1$ iterations for a graph with $n$ edges to stabilize via Bellman Ford if there are no negative edges.
|
||||
|
||||
If the graph stabilizes further from the $n$ iteration onwards, it contains negative cycles.
|
||||
|
||||
## 4
|
||||
|
||||
When Bellman-Ford performs a pass over all edges, does the order in which edges are relaxed within that single pass affect the final shortest path distances after all V−1 passes (assuming no negative cycles are present)?
|
||||
|
||||
**Answer:** No, the order of edge relaxation within a pass does not affect the final distances after all V−1 passes.
|
||||
|
||||
## 5
|
||||
|
||||
Which of the following statements accurately describe properties or uses of the Bellman-Ford algorithm?
|
||||
|
||||
**Answers:**
|
||||
- If a negative cycle is detected, the algorithm reports its presence and may not produce valid shortest paths for affected vertices.
|
||||
- The algorithm is suitable for distributed shortest path computation.
|
||||
|
||||
## 6
|
||||
|
||||
Given a graph where all edges have positive weights, the shortest path produced by Dijkstra's and Bellman Ford algorithm may be different but path weight would be same.
|
||||
|
||||
**Answer:** True
|
||||
|
||||
# Activity 3
|
||||
|
||||
## 1
|
||||
|
||||
What type of shortest path problem is the Floyd-Warshall algorithm designed to solve?
|
||||
|
||||
**Answer:** All-pairs shortest paths in graphs with negative edge weights or positive edge weights (but no negative cycles).
|
||||
|
||||
## 2
|
||||
|
||||
The core update rule in Floyd-Warshall is $$dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])$$
|
||||
|
||||
What does the variable k fundamentally represent in this context?
|
||||
|
||||
**Answer:** An intermediate vertex that might lie on a shortest path from i to j
|
||||
|
||||
## 3
|
||||
|
||||
What is the time complexity of the Floyd-Warshall algorithm for a graph with N vertices?
|
||||
|
||||
**Answer:** $O(N^3)$
|
||||
|
||||
## 4
|
||||
|
||||
How does the Floyd-Warshall algorithm detect the presence of a negative weight cycle in the graph?
|
||||
|
||||
**Answer:** By observing if any dist[i][i] (distance from a vertex to itself) becomes negative after all iterations
|
||||
|
||||
## 5
|
||||
|
||||
Consider a graph with 3 vertices {1, 2, 3}. The initial distance matrix dist is given as: dist[1][1] = 0, dist[1][2] = 2, dist[1][3] = 7 dist[2][1] = inf, dist[2][2] = 0, dist[2][3] = 3 dist[3][1] = inf, dist[3][2] = inf, dist[3][3] = 0
|
||||
|
||||
What is the value of dist[1][3] after the iteration where k = 2 is considered as the intermediate vertex?
|
||||
|
||||
**Answer:** 5
|
||||
|
||||
## 6
|
||||
|
||||
Consider a graph with 3 vertices {1, 2, 3}. The initial distance matrix dist is set up. dist[1][1]=0, dist[1] [2]=5, dist[1][3]=inf dist[2][1]=inf, dist[2][2]=0, dist[2][3]=2 dist[3][1]=inf, dist[3] [2]=inf, dist[3][3]=0
|
||||
|
||||
After all iterations of the Floyd-Warshall algorithm, what will be the value of $dist[3][1]$?
|
||||
|
||||
**Answer:** inf
|
||||
|
||||
Explanation: The distance of 3 to 1 is never updated.
|
||||
|
||||
|
||||
# Activity 4
|
||||
|
||||
|
||||
## 1
|
||||
|
||||
Prim's algorithm builds the Minimum Spanning Tree (MST) by iteratively adding edges. At each step, which type of edge does it always select?
|
||||
|
||||
**Answer:** The edge with the smallest weight that connects a vertex already in the MST to a vertex not yet in the MST
|
||||
|
||||
## 2
|
||||
|
||||
Consider the following undirected graph. If Prim's algorithm starts from vertex 'A', what is the total weight of the Minimum Spanning Tree (MST) it finds?
|
||||
|
||||
Graph: A-B (4), A-C (2), B-C (5), B-D (10), C-D (3), C-E (7), D-E (1)
|
||||
|
||||
**Answer:** 10
|
||||
|
||||
## 3
|
||||
|
||||
A connected, undirected graph has 6 vertices and 7 edges. If Prim's algorithm is used to find its Minimum Spanning Tree, how many edges will be included in the final MST?
|
||||
|
||||
**Answer:** 5
|
||||
|
||||
## 4
|
||||
|
||||
When is the Minimum Spanning Tree (MST) of a connected, weighted graph guaranteed to be unique?
|
||||
|
||||
**Answer:** If all edge weights in the graph are distinct.
|
||||
|
||||
## 5
|
||||
|
||||
Suppose Prim's algorithm has constructed an MST for a graph. If the weight of an edge not currently in the MST is decreased, will the existing MST always change?
|
||||
|
||||
**Answer:** Not necessarily; the MST will change only if the decreased edge becomes the new minimum edge across some cut that was previously crossed by a different (heavier) MST edge.
|
||||
|
||||
## 6
|
||||
|
||||
If Prim's algorithm has generated a Minimum Spanning Tree (MST) for a connected graph, the unique path between any two vertices within that MST is always the shortest path between those two vertices in the original graph
|
||||
|
||||
**Answer:** False
|
||||
|
||||
# Activity 5
|
||||
|
||||
## 1
|
||||
|
||||
Which of the following statements about how Kruskal's algorithm constructs the MST are true?
|
||||
|
||||
**Answer:** (Yes there is only one I think is correct)
|
||||
- It adds an edge only if it connects two vertices that belong to different existing components.
|
||||
|
||||
## 2
|
||||
|
||||
A graph has 5 vertices {V1, V2, V3, V4, V5}. Kruskal's algorithm is applied. Initially, each vertex is in its own set: {V1}, {V2}, {V3}, {V4}, {V5}. Consider the following sequence of edges processed by Kruskal's algorithm:
|
||||
|
||||
(V1, V2) - weight 2
|
||||
(V3, V4) - weight 3
|
||||
(V1, V3) - weight 4
|
||||
(V2, V4) - weight 5
|
||||
(V5, V2) - weight 6
|
||||
|
||||
How many distinct connected components are there after these 5 edges have been processed and decisions made?
|
||||
|
||||
**Answer:** 1
|
||||
|
||||
## 3
|
||||
|
||||
If Kruskal's algorithm considers an edge e and decides not to include it in the MST, what is the precise reason for this exclusion?
|
||||
|
||||
**Answer:** Adding edge e would connect two vertices that are already in the same connected component within the set of edges already chosen for the MST.
|
||||
|
||||
## 4
|
||||
|
||||
A graph has 7 vertices and consists of 3 distinct connected components. Kruskal's algorithm is executed on this graph. Assuming all components are non-empty and connected internally, how many edges will Kruskal's algorithm include in the resulting Minimum Spanning Forest (MSF)?
|
||||
|
||||
**Answer:** 4
|
||||
|
||||
## 5
|
||||
|
||||
If Kruskal's algorithm rejects an edge e (meaning e is not included in the MST), it implies that e is the heaviest edge in any cycle that e forms with edges already selected for the MST.
|
||||
|
||||
**Answer:** True
|
||||
|
||||
## 6
|
||||
|
||||
In a connected undirected graph with more than three vertices and all distinct edge weights, the two edges with the smallest weights will always be part of its Minimum Spanning Tree (MST).
|
||||
|
||||
**Answer:** True
|
||||
|
||||
|
||||
# GrPAs
|
||||
|
||||
## 1
|
||||
|
||||
We are implementing Kruskal's algorithm because it's just a tad bit easier than Prim's algorithm.
|
||||
|
||||
```python
|
||||
def FiberLink(wl):
|
||||
sum, edges, component = 0, [], {}
|
||||
for u, u_edges in wl.items():
|
||||
component[u] = u
|
||||
for v, d in u_edges:
|
||||
edges.append((d, u, v))
|
||||
edges.sort()
|
||||
|
||||
for d, u, v in edges:
|
||||
if component[v] == component[u]:
|
||||
continue
|
||||
sum += d
|
||||
c = component[u]
|
||||
for ckey, cval in component.items():
|
||||
if cval == c:
|
||||
component[ckey] = component[v]
|
||||
|
||||
return sum
|
||||
```
|
||||
|
||||
## 2
|
||||
|
||||
The shorted walk from `src` to `dst` while bouncing off the `bounce` node. We are using Bellman-Ford because simple is good.
|
||||
|
||||
We can find the shortest path from `bounce` to each of `src` and `dst` and then add up those two paths (both the path sequence and the weight).
|
||||
|
||||
```python
|
||||
def min_cost_walk(wl, src, dest, bounce):
|
||||
dist, parent = {}, {}
|
||||
for u in wl.keys():
|
||||
dist[u] = 1e6 # close to infinity
|
||||
dist[bounce] = 0
|
||||
|
||||
for _ in range(len(wl)):
|
||||
for u, edges in wl.items():
|
||||
for v, weight in edges:
|
||||
if dist[u] + weight < dist[v]:
|
||||
dist[v] = dist[u] + weight
|
||||
parent[v] = u
|
||||
|
||||
path = []
|
||||
revpath = []
|
||||
distance = dist[src] + dist[dest]
|
||||
while src != bounce:
|
||||
path.append(src)
|
||||
src = parent[src]
|
||||
|
||||
path.append(bounce)
|
||||
while dest != bounce:
|
||||
revpath.append(dest)
|
||||
dest = parent[dest]
|
||||
|
||||
return distance, path + revpath[::-1]
|
||||
```
|
||||
|
||||
## 3
|
||||
|
||||
Here again, we are using Bellman-Ford. Remember from the activity question answers that if there are any relaxations in the $n_{th}$ iteration,
|
||||
there exists a negative cycle in the graph.
|
||||
|
||||
|
||||
```python
|
||||
def IsNegativeWeightCyclePresent(wl):
|
||||
n = len(wl)
|
||||
dist = {}
|
||||
parent = {}
|
||||
for u in wl:
|
||||
dist[u] = 1e6
|
||||
dist[u] = 0 # the node to start with
|
||||
|
||||
for i in range(n):
|
||||
for u, edges in wl.items():
|
||||
for v, weight in edges:
|
||||
if dist[u] + weight < dist[v]:
|
||||
if i == n - 1:
|
||||
return True
|
||||
dist[v] = dist[u] + weight
|
||||
parent[v] = u
|
||||
|
||||
return False
|
||||
```
|
||||
|
||||
# GA
|
||||
|
||||
## 1
|
||||
At each step of Dijkstra's algorithm, after a vertex has been processed, how does the algorithm determine which unvisited vertex to process next?
|
||||
|
||||
Answer: It picks the unvisited vertex that has the smallest current shortest distance from the source.
|
||||
|
||||
## 2
|
||||
|
||||
Which of the following statements correctly describes how the Bellman-Ford algorithm detects the presence of a negative cycle reachable from the source? Consider that V is the number of vertices in the graph.
|
||||
|
||||
Answer: If, during a Vth pass over all edges, any distance value can still be improved (i.e., an edge relaxation occurs).
|
||||
|
||||
## 3
|
||||
|
||||
A graph has 4 vertices (V1, V2, V3, V4) and the following edges:
|
||||
|
||||
- V1 → V2 (weight = 2)
|
||||
- V2 → V3 (weight = -3)
|
||||
- V3 → V1 (weight = 0)
|
||||
- V1 → V4 (weight = 5)
|
||||
|
||||
If Bellman-Ford starts from V1, after running the algorithm for all necessary passes, how many vertices will have their shortest distance updated in the final (4-th) pass used for negative cycle detection?
|
||||
|
||||
Answer: 3
|
||||
|
||||
## 4
|
||||
|
||||
Consider any connected graph with 4 vertices and 6 edges, where all edge weights are distinct. In such a graph, the three edges with the smallest weights will always be part of its Minimum Spanning Tree (MST).
|
||||
|
||||
Answer: False
|
||||
|
||||
## 5
|
||||
|
||||
A graph can have a unique Minimum Spanning Tree (MST) only if all its edge weights are distinct
|
||||
|
||||
Answer: True
|
||||
|
||||
## 6
|
||||
|
||||
Suppose we run Prim's algorithm and Kruskal's algorithm on a graph G and these two algorithms
|
||||
produce minimum-cost spanning trees $T_P$ and $T_K$, respectively.
|
||||
|
||||
(I) $T_P$ may be different from $T_K$ if some pair of edges in G have the same weight.
|
||||
|
||||
(II) $T_P$ is always the same as $T_K$ if all edges in G have distinct weights.
|
||||
|
||||
Answer: Both (I) and (II) are correct.
|
||||
|
||||
## 7
|
||||
|
||||
Which one of the following can be the sequence of edges added, in that order, to create a minimum spanning tree using Kruskal’s algorithm?
|
||||
|
||||
Answers:
|
||||
|
||||
1. (a,b) (d,f) (b,f) (d,c) (d,e)
|
||||
2. (a,b) (d,f) (d,c) (b,f) (d,e)
|
||||
3. (d,f) (a,b) (d,c) (b,f) (d,e)
|
||||
5) (d,f) (a,b) (b,f) (d,c) (d,e)
|
||||
|
||||
## 8
|
||||
|
||||
Consider the given weighted adjacency matrix $w$ for a complete undirected graph with vertex
|
||||
set $\{0, 1, 2, 3, 4\}$. Where $w[i][j]$, $i \neq j$ in the matrix is the weight of the edge
|
||||
$(i,j)$.
|
||||
|
||||
$$w = \begin{pmatrix}
|
||||
0 & 1 & 8 & 1 & 4 \\
|
||||
1 & 0 & 12 & 4 & 9 \\
|
||||
8 & 12 & 0 & 7 & 3 \\
|
||||
1 & 4 & 7 & 0 & 2 \\
|
||||
4 & 9 & 3 & 2 & 0
|
||||
\end{pmatrix}$$
|
||||
|
||||
What is the weight of the minimum spanning tree for the given graph?
|
||||
|
||||
Answer: 7
|
||||
|
||||
## 9
|
||||
|
||||
Which of the following statement(s) is/are true about the spanning tree of a connected graph?
|
||||
|
||||
Answers:
|
||||
|
||||
- A spanning tree is a connected acyclic graph.
|
||||
- A spanning tree for an n vertex graph has exactly n-1 edges.
|
||||
- Adding an edge to a spanning tree must create a cycle.
|
||||
- In a spanning tree, every pair of nodes is connected by a unique path
|
||||
|
||||
## 10
|
||||
|
||||
Consider the following weighted adjacency list WList for a directed and connected graph. What will be the path weight of the shortest path from 1 to 3?
|
||||
|
||||
```python
|
||||
WList = {
|
||||
#source: [(destination, weight),...]
|
||||
1: [(2, 10), (8, 8)],
|
||||
2: [(6, 2)],
|
||||
3: [(2, 1), (4, 1)],
|
||||
4: [(5, 3)],
|
||||
5: [(6, -1)],
|
||||
6: [(3, -2)],
|
||||
7: [(2, -4), (6, -1)],
|
||||
8: [(7, 1)]
|
||||
}
|
||||
```
|
||||
|
||||
Answer: 5
|
||||
|
||||
## 11
|
||||
|
||||
Consider a complete undirected graph with vertex set {0, 1, 2, 3, 4}. Every entry W[i][j] where i≠j in the matrix W below is the weight of the edge from vertex i to vertex j.
|
||||
|
||||
$$w = \begin{pmatrix}
|
||||
0 & 1 & 8 & 1 & 4 \\
|
||||
1 & 0 & 12 & 4 & 9 \\
|
||||
8 & 12 & 0 & 7 & 3 \\
|
||||
1 & 4 & 7 & 0 & 2 \\
|
||||
4 & 9 & 3 & 2 & 0
|
||||
\end{pmatrix}$$
|
||||
|
||||
Answer: 4
|
||||
|
||||
|
||||
## 12
|
||||
|
||||
In the given graph, if we try to find the shortest path from node a to all other nodes using Dijkstra's algorithm, in what order do the nodes get included in the visited set?
|
||||
|
||||
Answer: a e d c b g f h
|
||||
|
||||
## 13
|
||||
|
||||
Consider the given graph. Which of the following is the correct sequence of edges added to the minimum spanning tree when Prim's algorithm is applied on this graph with 5 as the source vertex?
|
||||
|
||||
Answer: [(5,1),(1,2),(2,3),(3,4)]
|
||||
|
||||
|
||||
## 14
|
||||
|
||||
In the context of the Floyd-Warshall algorithm, what does it mean if the distance matrix has a negative value in its diagonal?
|
||||
|
||||
Answer: The graph has a negative-weight cycle.
|
||||
|
||||
## 15
|
||||
|
||||
Consider the graph G given. Let
|
||||
α denote the number of minimum spanning trees of G and
|
||||
β denote the weight of such a minimum spanning tree. The value of
|
||||
α+β is
|
||||
|
||||
Answer: 14
|
||||
@@ -1,154 +0,0 @@
|
||||
---
|
||||
title: "w8"
|
||||
date: 2025-10-03T16:04:18+05:30
|
||||
draft: false
|
||||
---
|
||||
|
||||
## GRPA 1
|
||||
|
||||
```python
|
||||
def findOccOf(arr, x):
|
||||
lo = 0
|
||||
hi = len(arr) - 1
|
||||
|
||||
loval = None
|
||||
while lo <= hi:
|
||||
mid = (lo + hi) // 2
|
||||
c = arr[mid]
|
||||
if x < c:
|
||||
hi = mid - 1
|
||||
elif x > c:
|
||||
lo = mid + 1
|
||||
elif x == c:
|
||||
loval = loval or mid
|
||||
loval = min(loval, mid)
|
||||
hi = mid - 1
|
||||
|
||||
lo = 0
|
||||
hi = len(arr) - 1
|
||||
hival = None
|
||||
while lo <= hi:
|
||||
mid = (lo + hi) // 2
|
||||
c = arr[mid]
|
||||
if x < c:
|
||||
hi = mid - 1
|
||||
elif x > c:
|
||||
lo = mid + 1
|
||||
elif x == c:
|
||||
hival = hival or mid
|
||||
hival = max(hival, mid)
|
||||
lo = mid + 1
|
||||
|
||||
|
||||
return loval, hival
|
||||
```
|
||||
|
||||
## GRPA 2
|
||||
|
||||
```python
|
||||
def merge_inversion(left, right):
|
||||
merged = []
|
||||
count = 0
|
||||
|
||||
i, j = 0, 0
|
||||
|
||||
m = len(left)
|
||||
n = len(right)
|
||||
while i + j < m + n:
|
||||
if j == n or (i != m and left[i] < right[j]):
|
||||
merged.append(left[i])
|
||||
i += 1
|
||||
continue
|
||||
|
||||
merged.append(right[j])
|
||||
j += 1
|
||||
count += m - i
|
||||
|
||||
return merged, count
|
||||
|
||||
|
||||
def sort_and_count(arr):
|
||||
n = len(arr)
|
||||
if n == 1:
|
||||
return arr, 0
|
||||
left = arr[: n // 2]
|
||||
right = arr[n // 2 :]
|
||||
|
||||
left, count_left = sort_and_count(left)
|
||||
right, count_right = sort_and_count(right)
|
||||
merged, count_both = merge_inversion(left, right)
|
||||
|
||||
return (merged, count_left + count_right + count_both)
|
||||
|
||||
def countIntersection(a, b):
|
||||
tuples = sorted(zip(a, b))
|
||||
b = [t[1] for t in tuples]
|
||||
return sort_and_count(b)[1]
|
||||
```
|
||||
|
||||
## GRPA 3
|
||||
|
||||
```python
|
||||
dist = lambda a, b: ((a[0]-b[0])**2 + (a[1]-b[1])**2)**.5
|
||||
|
||||
def closest_pair(Px, Py):
|
||||
n = len(Px)
|
||||
if n <= 3:
|
||||
min_d = float('inf')
|
||||
for i in range(n):
|
||||
for j in range(i + 1, n):
|
||||
min_d = min(min_d, dist(Px[i], Px[j]))
|
||||
return min_d
|
||||
|
||||
mid = n // 2
|
||||
Qx = Px[:mid]
|
||||
Rx = Px[mid:]
|
||||
mid_point = Qx[-1][0]
|
||||
|
||||
Qy = []
|
||||
Ry = []
|
||||
for p in Py:
|
||||
if p[0] <= mid_point:
|
||||
Qy.append(p)
|
||||
else:
|
||||
Ry.append(p)
|
||||
|
||||
min_d = min(closest_pair(Qx, Qy), closest_pair(Rx, Ry))
|
||||
|
||||
Sy = [p for p in Py if mid_point - min_d <= p[0] <= mid_point + min_d]
|
||||
for i in range(len(Sy)):
|
||||
for j in range(i + 1, len(Sy)):
|
||||
if Sy[j][1] - Sy[i][1] >= min_d:
|
||||
break
|
||||
min_d = min(min_d, dist(Sy[i], Sy[j]))
|
||||
|
||||
return min_d
|
||||
|
||||
|
||||
def minDistance(points):
|
||||
Px = sorted(points, key=lambda p: p[0])
|
||||
Py = sorted(points, key=lambda p: p[1])
|
||||
return round(closest_pair(Px, Py), 2)
|
||||
```
|
||||
|
||||
## GRPA 4
|
||||
|
||||
```python
|
||||
def mid(a):
|
||||
if len(a) <= 7:
|
||||
return sorted(a)[len(a)//2]
|
||||
|
||||
m = []
|
||||
for i in range(0,len(a), 7):
|
||||
m.append(mid(a[i:i+7]))
|
||||
|
||||
return mid(m)
|
||||
|
||||
def MoM7Pos(arr):
|
||||
m = mid(arr)
|
||||
pos = 0
|
||||
for x in arr:
|
||||
if x < m:
|
||||
pos += 1
|
||||
return pos
|
||||
```
|
||||
@@ -1,85 +0,0 @@
|
||||
---
|
||||
title: "note skta4v7n8h8"
|
||||
date: 2025-10-31T20:24:35+05:30
|
||||
draft: false
|
||||
---
|
||||
|
||||
# GrPA 1
|
||||
|
||||
```python
|
||||
from typing import List
|
||||
|
||||
def constructWord(s: str, chunks: List[str]) -> List[List[str]]:
|
||||
memo = {}
|
||||
|
||||
def solve(remaining_suffix: str) -> List[List[str]]:
|
||||
if not remaining_suffix:
|
||||
return [[]]
|
||||
|
||||
if remaining_suffix in memo:
|
||||
return memo[remaining_suffix]
|
||||
|
||||
possible_combos = []
|
||||
|
||||
for chunk in chunks:
|
||||
if not remaining_suffix.startswith(chunk):
|
||||
continue
|
||||
|
||||
leftover_results = solve(remaining_suffix[len(chunk):])
|
||||
if not leftover_results:
|
||||
continue
|
||||
|
||||
for rest in leftover_results:
|
||||
possible_combos.append([chunk] + rest)
|
||||
|
||||
memo[remaining_suffix] = possible_combos
|
||||
return possible_combos
|
||||
|
||||
return solve(s)
|
||||
```
|
||||
|
||||
# GrPA 2
|
||||
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
def MaxCoinPath(M, x1, y1, x2, y2):
|
||||
M = np.array(M, dtype=int)[x1:x2+1, y1:y2+1]
|
||||
cost = np.zeros((M.shape[0]+1, M.shape[1]+1), dtype=int)
|
||||
|
||||
for i in range(M.shape[0]-1, -1, -1):
|
||||
for j in range(M.shape[1]-1, -1, -1):
|
||||
cost[i, j] = max(M[i, j] + cost[i+1, j], M[i, j] + cost[i, j+1])
|
||||
return cost[0,0]
|
||||
```
|
||||
|
||||
# GrPA 3
|
||||
|
||||
```python
|
||||
def LDS(arr):
|
||||
n = len(arr)
|
||||
if n == 0:
|
||||
return []
|
||||
|
||||
memo = [1] * n
|
||||
parent = [-1] * n
|
||||
max_len = 0
|
||||
end_index = -1
|
||||
|
||||
for i in range(n):
|
||||
for j in range(i):
|
||||
if arr[i] < arr[j] and memo[i] < memo[j] + 1:
|
||||
memo[i] = memo[j] + 1
|
||||
parent[i] = j
|
||||
|
||||
if memo[i] > max_len:
|
||||
max_len = memo[i]
|
||||
end_index = i
|
||||
|
||||
subsequence = []
|
||||
current_index = end_index
|
||||
while current_index != -1:
|
||||
subsequence.append(arr[current_index])
|
||||
current_index = parent[current_index]
|
||||
return subsequence[::-1]
|
||||
```
|
||||
Reference in New Issue
Block a user