Skip to content

Commit 0550787

Browse files
committed
chore: Remove useless folders
1 parent 0c83137 commit 0550787

File tree

48 files changed

+1363
-852
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1363
-852
lines changed

bin/main/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Running On Custom Inputs
2+
3+
This folder allows you to pass user input and view the output after running the desired algorithm.
4+
5+
Simply run the file via IntelliJ in the respective folder.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Binary Search
2+
Binary search is a search algorithm that finds the position of a target value within a sorted array or list. It compares
3+
the target value to the middle element of the search range, then, based on the comparison, narrows the search to the
4+
upper or lower half of the current search range.
5+
6+
Two versions of binary search has been implemented in this repository - BinarySearch and BinarySearchTemplated.
7+
8+
## BinarySearch
9+
![binary search img](../../../../../docs/assets/images/BinarySearch.png)
10+
Image Source: GeeksforGeeks
11+
12+
BinarySearch is a more straightforward and intuitive version of the binary search algorithm. In this approach, after the
13+
mid-value is calculated, the high or low pointer is adjusted by just one unit. From the above example, after mid points
14+
to index 4 in the first search, the low pointer moves to index 5 (+1 from 4) when narrowing the search. Similarly, when
15+
mid points to index 7 in the second search, the high pointer shifts to index 6 (-1 from 7) when narrowing the search.
16+
This prevents any possibility of infinite loops. During the search, the moment mid-value is equal to the target value,
17+
the search ends prematurely. Note that there is no need for a "condition" method as the condition is already captured
18+
in the predicates of the if-else blocks.
19+
20+
## BinarySearchTemplated
21+
22+
BinarySearchTemplated removes the condition that checks if the current mid-value is equal to the target (which helps to
23+
end the search the moment the target is found). The template adds a "condition" method which will be modified based on
24+
the requirements of the implementation.
25+
26+
The narrowing of the search space differs from BinarySearch - only the high pointer will be adjusted by one unit.
27+
28+
This template will work for most binary search problems and will only require the following changes:
29+
- Search space (high and low)
30+
- Condition method
31+
- Returned value (low or low - 1)
32+
33+
### Search Space (Requires change)
34+
Simply modify the initialisation of the high and low pointer according to the [search space](#search-space-adjustment).
35+
36+
### Condition (Requires change)
37+
We assume that when the condition returns true, the current value "passes" and when the condition returns false, the
38+
current value "fails".
39+
40+
Note that in this template, the conditional blocks
41+
```
42+
if (condition(x)) {
43+
high = mid;
44+
} else {
45+
low = mid + 1;
46+
}
47+
```
48+
requires elements that "fail" the condition to be on the left of the elements that "pass" the condition, see below, in a
49+
sorted array due to the way the high and low pointers are reassigned.
50+
51+
![binary search templated 1 img](../../../../../docs/assets/images/BinarySearchTemplated1.jpeg)
52+
53+
Hence, we will need to implement a condition method that is able to discern between arrays that "pass" and "fail"
54+
accurately and also place them in the correct relative positions i.e. "fail" on the left of "pass". Suppose we change
55+
the condition method implementation in BinarySearchTemplated from `value >= target` to `value <= target`, what will
56+
happen?
57+
<details>
58+
<summary> <b>what will happen?</b> </summary>
59+
The array becomes "P P F F F F" and the low and high pointers are now reassigned wrongly.
60+
</details>
61+
62+
### Returned Value (Requires change)
63+
In this implementation of BinarySearchTemplated, we return the first "pass" in the array with `return low`. This is
64+
because our condition method implementation encompasses the target value that we are finding i.e. when
65+
`value == target`.
66+
67+
```java
68+
public static boolean condition(int value, int target) {
69+
return value >= target;
70+
}
71+
```
72+
![binary search templated 1 img](../../../../../docs/assets/images/BinarySearchTemplated2.jpeg)
73+
74+
However, if we want to return the last "fail" in the array, we will `return low - 1`.
75+
76+
Suppose now we modify the condition to be `value > target`, how can we modify our BinarySearchTemplated to still work as
77+
expected?
78+
<details>
79+
<summary> <b>value > target?</b> </summary>
80+
Replace `return low` with `return low - 1` and replace arr[low] with arr[low - 1] as now the target value is the last
81+
"fail".
82+
</details>
83+
84+
85+
### Search Space Adjustment
86+
What should be the search space adjustment? Why is only low reassigned with an increment and not high?
87+
88+
Due to the nature of floor division in Java's \ operator, if there are two mid-values within the search range, which is
89+
when the number of elements is even, the first mid-value will be selected. Suppose we do not increment the low pointer
90+
during reassignment, `low = mid`, let us take a look at the following example:
91+
92+
![binary search templated 1 img](../../../../../docs/assets/images/BinarySearchTemplated3.jpeg)
93+
94+
The search space has been narrowed down to the range of index 1 (low) to 2 (high). The mid-value is calculated,
95+
`mid = (1 + 2) / 2`, to be 1 due to floor division. Since `2 < 5`, we enter the else block where there is reassignment
96+
of `low = mid`. This means that the low pointer is still pointing to index 1 and the high pointer remains unchanged at
97+
index 2. This results in an infinite loop as the search range is not narrowed down.
98+
99+
To resolve this issue, we need `low = mid + 1`, which will result in the low pointer pointing to index 2 in this
100+
scenario. We still ensure correctness because the mid-value is not the target value, as the mid-value < target, and we
101+
can safely exclude it from the search range.
102+
103+
Why do we not need to increment the high pointer during reassignment? This is because the mid-value could be the target
104+
as the condition implemented is `value >= target`, hence, we cannot exclude it from the search range.
105+
106+
See [here](./binarySearchTemplatedExamples/README.md) to use the template for other problems
107+
108+
Credits: [Powerful Ultimate Binary Search Template](https://leetcode.com/discuss/general-discussion/786126/python-powerful-ultimate-binary-search-template-solved-many-problems)
109+
110+
## Complexity Analysis
111+
**Time**:
112+
- Worst case: O(log n)
113+
- Average case: O(log n)
114+
- Best case:
115+
- BinarySearch O(1)
116+
- BinarySearchTemplated O(log n)
117+
118+
BinarySearch:
119+
In the worst case, the target is either in the first index or does not exist in the array at all.
120+
In the best case, the target is the middle (odd number of element) or the first middle element (even number of elements)
121+
if floor division is used to determine the middle.
122+
123+
BinaryTemplated:
124+
In all cases, O(log n) iterations will be required as there is no condition to exit the loop prematurely.
125+
126+
**Space**: O(1) since no new data structures are used and searching is only done within the array given
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# BinarySearchTemplated Examples
2+
3+
We will be utilising the BinarySearchTemplated implementation to solve some problems.
4+
5+
The following will differ between problems:
6+
- Search Space
7+
- Condition
8+
- Returned Value
9+
10+
<b> How do we know if a problem can be solved with this template? </b>
11+
12+
A problem is well-suited for this approach when it meets the following criteria:
13+
14+
- <b> Clear Distinction Between Categories: </b> There should be a definitive way to categorize elements into two
15+
groups: "pass" and "fail".
16+
17+
- <b> Grouped Categories: </b> All the elements in one category should be grouped together without interspersion. This
18+
implies that if we move from a "fail" element to a "pass" one, all subsequent elements will be "pass".
19+
20+
- <b> Monotonic Property: </b> There needs to be a consistent, unidirectional trend or property in the search space.
21+
This means the condition being checked either consistently increases or decreases. For the classical binary search on a
22+
sorted array, this monotonic property is the sorted order of the elements, where the array elements increase
23+
(or decrease) consistently.
24+
25+
## 1. First Bad Version [Easy]
26+
27+
### Problem:
28+
29+
You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of
30+
your product fails the quality check. Since each version is developed based on the previous version, all the versions
31+
after a bad version are also bad.
32+
33+
Suppose you have `n` versions `[1, 2, ..., n]` and you want to find out the first bad one, which causes all the
34+
following ones to be bad.
35+
36+
You are given an API bool `isBadVersion(version)` which returns whether `version` is bad. Implement a function to find
37+
the first bad version. You should minimize the number of calls to the API.
38+
39+
Example 1:
40+
```
41+
Input: n = 5, bad = 4
42+
Output: 4
43+
Explanation:
44+
call isBadVersion(3) -> false
45+
call isBadVersion(5) -> true
46+
call isBadVersion(4) -> true
47+
Then 4 is the first bad version.
48+
```
49+
50+
### Solution:
51+
52+
<b> Search Space </b>
53+
54+
The search space includes all possible values.
55+
56+
```java
57+
high = n - 1;
58+
low = 0;
59+
```
60+
61+
<b> Condition </b>
62+
63+
The condition has already been implemented. But we need to check if the elements that pass the condition will be on the
64+
right of those that fail! Since "all the versions after a bad version are also bad", our template will work.
65+
66+
<b> Returned Value </b>
67+
68+
Since we want to return the first bad version, we will return low.
69+
70+
![first bad version img](../../../../../../docs/assets/images/firstBadVersion.jpeg)
71+
72+
<b> Full Solution: </b>
73+
74+
```java
75+
public int firstBadVersion(int n) {
76+
int high = n - 1; // max index for n elements
77+
int low = 0;
78+
while (low < high) {
79+
int mid = low + (high - low) / 2;
80+
if (isBadVersion(mid)) { // condition is isBadVersion
81+
high = mid;
82+
} else {
83+
low = mid + 1;
84+
}
85+
}
86+
87+
return low; // return first "pass"
88+
}
89+
```
90+
91+
## 2. Capacity To Ship Packages Within D Days [Medium]
92+
93+
### Problem:
94+
95+
A conveyor belt has packages that must be shipped from one port to another within `days` days.
96+
97+
The `ith` package on the conveyor belt has a weight of `weights[i]`. Each day, we load the ship with packages on the
98+
conveyor belt (in the order given by `weights`). We may not load more weight than the maximum weight capacity of the
99+
ship.
100+
101+
Return the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped
102+
within `days` days.
103+
104+
Example 1:
105+
```
106+
Input: weights = [1,2,3,4,5,6,7,8,9,10], days = 5
107+
Output: 15
108+
Explanation: A ship capacity of 15 is the minimum to ship all the packages in 5 days like this:
109+
1st day: 1, 2, 3, 4, 5
110+
2nd day: 6, 7
111+
3rd day: 8
112+
4th day: 9
113+
5th day: 10
114+
115+
Note that the cargo must be shipped in the order given, so using a ship of capacity 14 and splitting the packages into
116+
parts like (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) is not allowed.
117+
```
118+
119+
### Solution:
120+
121+
On first glance, while we are given an array, simply binary searching the array does not solve the problem. However,
122+
since our goal is to determine the least weight capacity of the ship, could this be our "target"? The answer is yes.
123+
By having each element being a least weight capacity case, with the lowest index being the heaviest weight and the
124+
highest index being the sum of all weights, we will have our search space. The monotonic property present is that if
125+
we can ship all packages within `D` days with capacity `m`, we can definitely ship them within `D` days with any
126+
capacity greater than `m`, such as `m + 1`.
127+
128+
<b> Search Space </b>
129+
130+
The search space is the range of least weight capacity we should search. The minimum least weight capacity that must be
131+
required is the heaviest package as we cannot split the heaviest package. The maximum least weight capacity that is
132+
necessary is the sum of all weights - i.e. we have to ship all packages within `1` day.
133+
134+
```java
135+
int sum = 0;
136+
for (i = 0; i < weights.length; i++) {
137+
sum += weights[i];
138+
}
139+
high = sum;
140+
low = weights[weights.length - 1];
141+
```
142+
143+
<b> Condition </b>
144+
145+
The condition is to check if it is feasible to ship all packages within `D` days with a least weight capacity of `m`.
146+
Where `D` is given and `m` is the mid-value in our search range.
147+
148+
```java
149+
public static boolean isFeasible(int[] weights, int days, int capacity) {
150+
int daysNeeded = 1;
151+
int currentWeight = 0;
152+
for (int i = 0; i < weights.length; i++) {
153+
if (currentWeight + weights[i] > capacity) {
154+
daysNeeded++;
155+
currentWeight = 0; // Reset current weight as we are starting a new day
156+
}
157+
currentWeight += weights[i];
158+
}
159+
return daysNeeded <= days; // If days needed is less than or equal to days, it is feasible
160+
}
161+
```
162+
163+
<b> Returned Value </b>
164+
165+
Since we want to return the minimum least weight capacity where we can deliver in time, we will return low.
166+
167+
<b> Full Solution: </b>
168+
169+
```java
170+
public int shipWithinDays(int[] weights, int days) {
171+
public boolean isFeasible(int[] weights, int days, int capacity) {
172+
int daysNeeded = 1;
173+
int currentWeight = 0;
174+
for (int i = 0; i < weights.length; i++) {
175+
if (currentWeight + weights[i] > capacity) {
176+
daysNeeded++;
177+
currentWeight = 0; // Reset current weight as we are starting a new day
178+
}
179+
currentWeight += weights[i];
180+
}
181+
return daysNeeded <= days;
182+
}
183+
184+
int sum = 0;
185+
for (i = 0; i < weights.length; i++) {
186+
sum += weights[i];
187+
}
188+
189+
high = sum;
190+
low = weights[weights.length - 1];
191+
192+
while (low < high) {
193+
int mid = low + (high - low) / 2;
194+
if (isFeasible(weights, days, mid)) { // condition is isFeasible
195+
high = mid;
196+
} else {
197+
low = mid + 1;
198+
}
199+
}
200+
201+
return low; // return first "pass"
202+
}
203+
```
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Knuth-Moris-Pratt Algorithm
2+
3+
KMP match is a type of pattern-searching algorithm.
4+
Pattern-searching problems is prevalent across many fields of CS, for instance,
5+
in text editors when searching for a pattern, in computational biology sequence matching problems,
6+
in NLP problems, and even for looking for file patterns for effective file management.
7+
It is hence crucial that we develop an efficient algorithm.
8+
9+
![KMP](../../../../../docs/assets/images/kmp.png)
10+
Image Source: GeeksforGeeks
11+
12+
## Analysis
13+
**Time complexity**:
14+
15+
Naively, we can look for patterns in a given sequence in O(nk) where n is the length of the sequence and k
16+
is the length of the pattern. We do this by iterating every character of the sequence, and look at the
17+
immediate k-1 characters that come after it. This is not a big issue if k is known to be small, but there's
18+
no guarantee this is the case.
19+
20+
KMP does this in O(n+k) by making use of previously identified sub-patterns. It identifies sub-patterns
21+
by first processing the pattern input in O(k) time, allowing identification of patterns in
22+
O(n) traversal of the sequence. More details found in the src code.
23+
24+
**Space complexity**: O(k) auxiliary space to store suffix that matches with prefix of the pattern string
25+
26+
## Notes
27+
A detailed illustration of how the algorithm works is shown in the code.
28+
But if you have trouble understanding the implementation,
29+
here is a good [video](https://www.youtube.com/watch?v=EL4ZbRF587g) as well.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Bubble Sort
2+
Bubble sort is one of the more intuitive comparison-based sorting algorithms.
3+
It makes repeated comparisons between neighbouring elements, 'bubbling' (side-by-side swaps)
4+
largest (or smallest) element in the unsorted region to the sorted region (often the front or the back).
5+
6+
![bubble sort img](../../../../../../docs/assets/images/BubbleSort.jpeg)
7+
8+
## Complexity Analysis
9+
**Time**:
10+
- Worst case (reverse sorted array): O(n^2)
11+
- Average case: O(n^2)
12+
- Best case (sorted array): O(n)
13+
14+
In the worst case, during each iteration of the outer loop, the number of adjacent comparisons is upper-bounded
15+
by n. Since BubbleSort requires (n-1) iterations of the outer loop to sort the entire array, the total number
16+
of comparisons performed can be upper-bounded by (n-1) * n ≈ n^2.
17+
18+
This implementation of BubbleSort terminates the outer loop once there are no swaps within one iteration of the
19+
outer loop. This improves the best case time complexity to O(n) for an already sorted array.
20+
21+
**Space**: O(1) since sorting is done in-place

0 commit comments

Comments
 (0)