Skip to content

Commit e502e06

Browse files
authored
Merge pull request #48 from harisdev-netizen/harisdev-branch
Harisdev-branch
2 parents 5154885 + d72e3fd commit e502e06

File tree

4 files changed

+325
-0
lines changed

4 files changed

+325
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# 0005 Trapping Rain Water ( L-A )
2+
3+
## Problem
4+
5+
A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Given the locations and heights of all the buildings, return the skyline formed by these buildings collectively.
6+
7+
The geometric information of each building is given in the array `buildings` where `buildings[i] = [lefti, righti, heighti]`:
8+
9+
- `lefti` is the x coordinate of the left edge of the ith building.
10+
- `righti` is the x coordinate of the right edge of the ith building.
11+
- `heighti` is the height of the ith building.
12+
13+
You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.
14+
15+
## Example 1
16+
17+
```
18+
Input: buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
19+
Output: [[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
20+
Explanation:
21+
Figure A shows the buildings of the input.
22+
Figure B shows the skyline formed by those buildings. The red points in figure B represent the key points in the output list.
23+
```
24+
25+
## Solution Pseudocode
26+
27+
```javascript
28+
Function getSkyline(buildings):
29+
// base case
30+
if (length(buildings) == 1):
31+
return [(buildings[0].left, buildings[0].height), (buildings[0].right, 0)]
32+
33+
// divide the buildings into two groups
34+
mid = length(buildings) // 2
35+
left = getSkyline(buildings[:mid])
36+
right = getSkyline(buildings[mid:])
37+
38+
// merge the two groups
39+
return merge(left, right)
40+
41+
Function merge(left, right):
42+
// initialize the pointers and the result array
43+
i, j = 0, 0
44+
result = []
45+
left_height, right_height = 0, 0
46+
// merge the two lists
47+
while (i < len(left) and j < len(right)):
48+
if (left[i][0] < right[j][0]):
49+
x = left[i][0]
50+
left_height = left[i][1]
51+
height = max(left_height, right_height)
52+
result.append((x, height))
53+
i += 1
54+
else:
55+
x = right[j][0]
56+
right_height = right[j][1]
57+
height = max(left_height, right_height)
58+
result.append((x, height))
59+
j += 1
60+
// append the remaining points from left or right
61+
while (i < len(left)):
62+
result.append(left[i])
63+
i += 1
64+
while (j < len(right)):
65+
result.append(right[j])
66+
j += 1
67+
68+
return result
69+
70+
```
71+
72+
## How it works
73+
- The `getSkyline` function is the main function that takes in a list of buildings as input and returns the skyline as a list of points. The function first checks if there is only one building in the list, in which case it returns two points representing the left and right boundaries of the building.
74+
- If there are more than one building in the list, the function recursively divides the buildings into two groups using the midpoint, and calls itself on each group. The results from the two recursive calls are then merged using the `merge` function.
75+
- The `merge` function takes in two lists of points representing the skylines of the left and right groups and merges them into a single list. The function initializes two pointers, `i` and `j`, to 0 and sets `left_height` and `right_height` to 0. The `result` array is used to store the merged skyline.
76+
- The function then uses a while loop to iterate over the two input lists. At each iteration, it compares the x-coordinates of the points at the current positions of the two pointers. If the x-coordinate of the point in the left list is less than the x-coordinate of the point in the right list, it means that the left building is closer to the viewer, so the function uses the left building's height to update the `left_height` variable and calculates the maximum height between `left_height` and `right_height`. The function then appends a new point with the x-coordinate and maximum height to the `result` array, and increments the `i` pointer.
77+
- If the x-coordinate of the point in the right list is less than or equal to the x-coordinate of the point in the left list, it means that the right building is closer to the viewer, so the function uses the right building's height to update the `right_height` variable
78+
79+
## References
80+
81+
- [LeetCode](https://leetcode.com/problems/the-skyline-problem/)
82+
83+
## Problem Added By
84+
85+
- [Haris](https://github.com/harisdev-netizen)
86+
87+
## Contributing
88+
89+
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
90+
91+
Please make sure to update tests as appropriate.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
class Heap {
2+
constructor(compareFunc) {
3+
this.compare = compareFunc || ((a, b) => a - b);
4+
this.elements = [];
5+
}
6+
7+
get size() {
8+
return this.elements.length;
9+
}
10+
11+
get top() {
12+
return this.elements[0];
13+
}
14+
15+
push(element) {
16+
this.elements.push(element);
17+
this.heapifyUp();
18+
}
19+
20+
pop() {
21+
const top = this.elements[0];
22+
const bottom = this.elements.pop();
23+
if (this.elements.length > 0) {
24+
this.elements[0] = bottom;
25+
this.heapifyDown();
26+
}
27+
return top;
28+
}
29+
30+
heapifyUp() {
31+
let current = this.elements.length - 1;
32+
while (current > 0) {
33+
const parent = Math.floor((current - 1) / 2);
34+
if (this.compare(this.elements[current], this.elements[parent]) < 0) {
35+
[this.elements[current], this.elements[parent]] = [this.elements[parent], this.elements[current]];
36+
current = parent;
37+
} else {
38+
break;
39+
}
40+
}
41+
}
42+
43+
heapifyDown() {
44+
let current = 0;
45+
while (current < this.elements.length) {
46+
let child = null;
47+
const left = current * 2 + 1;
48+
const right = current * 2 + 2;
49+
if (left < this.elements.length && this.compare(this.elements[left], this.elements[current]) < 0) {
50+
child = left;
51+
}
52+
if (right < this.elements.length && this.compare(this.elements[right], this.elements[current]) < 0
53+
&& this.compare(this.elements[right], this.elements[left]) < 0) {
54+
child = right;
55+
}
56+
if (child !== null) {
57+
[this.elements[current], this.elements[child]] = [this.elements[child], this.elements[current]];
58+
current = child;
59+
} else {
60+
break;
61+
}
62+
}
63+
}
64+
}
65+
66+
function getSkyline(buildings) {
67+
const n = buildings.length;
68+
const criticalPoints = new Heap((a, b) => a[0] !== b[0] ? a[0] - b[0] : b[1] - a[1]);
69+
for (let i = 0; i < n; i++) {
70+
const [left, right, height] = buildings[i];
71+
criticalPoints.push([left, -height, i]);
72+
criticalPoints.push([right, height, i]);
73+
}
74+
const activeBuildings = new Heap((a, b) => b[1] - a[1]);
75+
const skyline = [[0, 0]];
76+
while (criticalPoints.size > 0) {
77+
const [x, h, i] = criticalPoints.top;
78+
const isStart = h < 0;
79+
const height = Math.abs(h);
80+
if (isStart) {
81+
activeBuildings.push([buildings[i][2], buildings[i][1]]);
82+
} else {
83+
activeBuildings.elements.forEach(([ah, ar], j) => {
84+
if (j === i) {
85+
activeBuildings.elements[j] = activeBuildings.elements[activeBuildings.size - 1];
86+
activeBuildings.elements.pop();
87+
activeBuildings.heapifyDown();
88+
return;
89+
}
90+
if (ar > buildings[i][0]) {
91+
skyline.push([x, Math.min(height, ah)]);
92+
if (ar > buildings[i][1]) {
93+
activeBuildings.elements[j][1] = buildings[i][1];
94+
activeBuildings.heapifyDown();
95+
}
96+
}
97+
});
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# 0005 Longest Common Subsequence ( L-A )
2+
3+
## Problem
4+
5+
Given two strings, find the length of their longest common subsequence (LCS). A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements.
6+
7+
## Example 1
8+
9+
```
10+
Input:
11+
str1 = "ABCDGH"
12+
str2 = "AEDFHR"
13+
14+
Output:
15+
The longest common subsequence is "ADH" with a length of 3.
16+
17+
Input:
18+
str1 = "AGGTAB"
19+
str2 = "GXTXAYB"
20+
21+
Output:
22+
The longest common subsequence is "GTAB" with a length of 4.
23+
```
24+
25+
## Solution Pseudocode
26+
27+
```javascript
28+
function longestCommonSubsequence(str1, str2) {
29+
const m = str1.length;
30+
const n = str2.length;
31+
32+
// Initialize a 2D array with 0
33+
const lcs = Array(m + 1)
34+
.fill()
35+
.map(() => Array(n + 1).fill(0));
36+
37+
// Fill the 2D array with LCS lengths
38+
for (let i = 1; i <= m; i++) {
39+
for (let j = 1; j <= n; j++) {
40+
if (str1[i - 1] === str2[j - 1]) {
41+
lcs[i][j] = lcs[i - 1][j - 1] + 1;
42+
} else {
43+
lcs[i][j] = Math.max(lcs[i - 1][j], lcs[i][j - 1]);
44+
}
45+
}
46+
}
47+
48+
// Return the length of LCS
49+
return lcs[m][n];
50+
}
51+
52+
// Example usage
53+
const str1 = "ABCDGH";
54+
const str2 = "AEDFHR";
55+
const result = longestCommonSubsequence(str1, str2);
56+
console.log(result); // Output: 3
57+
58+
// Another example
59+
const str3 = "AGGTAB";
60+
const str4 = "GXTXAYB";
61+
const result2 = longestCommonSubsequence(str3, str4);
62+
console.log(result2); // Output: 4
63+
```
64+
65+
## How it works
66+
67+
- The code returns an object with two properties: `length`, which is the length of the longest common subsequence, and `sequence`, which is the actual subsequence itself.
68+
- It also includes a section of code to trace back the 2D array and find the actual LCS string.
69+
- The time complexity of this algorithm is O(mn), where m and n are the lengths of the input strings.
70+
71+
## References
72+
73+
- [Google](https://www.google.com/search?client=opera&q=Longest+Common+Subsequence&sourceid=opera&ie=UTF-8&oe=UTF-8)
74+
75+
## Problem Added By
76+
77+
- [Haris](https://github.com/harisdev-netizen)
78+
79+
## Contributing
80+
81+
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
82+
83+
Please make sure to update tests as appropriate.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
function longestCommonSubsequence(str1, str2) {
2+
const m = str1.length;
3+
const n = str2.length;
4+
5+
// Initialize a 2D array with 0
6+
const lcs = Array(m + 1)
7+
.fill()
8+
.map(() => Array(n + 1).fill(0));
9+
10+
// Fill the 2D array with LCS lengths
11+
for (let i = 1; i <= m; i++) {
12+
for (let j = 1; j <= n; j++) {
13+
if (str1[i - 1] === str2[j - 1]) {
14+
lcs[i][j] = lcs[i - 1][j - 1] + 1;
15+
} else {
16+
lcs[i][j] = Math.max(lcs[i - 1][j], lcs[i][j - 1]);
17+
}
18+
}
19+
}
20+
21+
// Find the LCS string by tracing back the 2D array
22+
let i = m;
23+
let j = n;
24+
let lcsStr = "";
25+
26+
while (i > 0 && j > 0) {
27+
if (str1[i - 1] === str2[j - 1]) {
28+
lcsStr = str1[i - 1] + lcsStr;
29+
i--;
30+
j--;
31+
} else if (lcs[i - 1][j] > lcs[i][j - 1]) {
32+
i--;
33+
} else {
34+
j--;
35+
}
36+
}
37+
38+
return {
39+
length: lcs[m][n],
40+
sequence: lcsStr,
41+
};
42+
}
43+
44+
// Example usage
45+
const str1 = "ABCDGH";
46+
const str2 = "AEDFHR";
47+
const result = longestCommonSubsequence(str1, str2);
48+
console.log(result); // Output: { length: 3, sequence: 'ADH' }
49+
50+
// Another example
51+
const str3 = "AGGTAB";
52+
const str4 = "GXTXAYB";
53+
const result2 = longestCommonSubsequence(str3, str4);
54+
console.log(result2); // Output: { length: 4, sequence: 'GTAB' }

0 commit comments

Comments
 (0)