Skip to content

Commit 253a8b4

Browse files
committed
Add more problems.
1 parent 5cbcdc9 commit 253a8b4

9 files changed

+532
-0
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ A collection of JavaScript problems and solutions for studying algorithms.
113113
- [First Missing Positive](src/array/first-missing-positive.js)
114114
- [Missing Ranges](src/array/missing-ranges.js)
115115
- [Majority Elements](src/array/majority-element.js)
116+
- [Find All Duplicates in an Array](src/array/find-all-duplicates-in-an-array.js)
117+
- [Third Maximum Number](src/array/third-maximum-number.js)
118+
- [Split Array with Equal Sum](src/array/split-array-with-equal-sum.js)
119+
- [Maximum Swap](src/array/maximum-swap.js)
120+
- [Candy Crush](src/candy-crush.js)
116121

117122
### Matrix
118123

@@ -122,6 +127,7 @@ A collection of JavaScript problems and solutions for studying algorithms.
122127
- [Diagonal Traverse](src/matrix/diagonal-traverse.js)
123128
- [Number Of Corner Rectangles](src/matrix/number-of-corner-rectangles.js)
124129
- [Lonely Pixel I](src/matrix/lonely-pixel-i.js)
130+
- [Lonely Pixel II](src/matrix/lonely-pixel-ii.js)
125131
- [Sparse Matrix Multiplication](src/matrix/sparse-matrix-multiplication.js)
126132
- [Escape The Ghosts](src/matrix/escape-the-ghosts.js)
127133
- [Brick Wall](src/matrix/brick-wall.js)
@@ -366,6 +372,7 @@ A collection of JavaScript problems and solutions for studying algorithms.
366372
### Depth First Search
367373

368374
- [Number of Islands](src/dfs/number-of-islands.js)
375+
- [Max Area of Island](src/dfs/max-area-of-island.js)
369376
- [Next Closest Time](src/dfs/next-closest-time.js)
370377
- [Decode String](src/dfs/decode-string.js)
371378
- [Pacific Atlantic Water Flow](src/dfs/pacific-atlantic-water-flow.js)
@@ -444,6 +451,7 @@ A collection of JavaScript problems and solutions for studying algorithms.
444451
- [Largest Sum of Averages](src/dynamic-programing/largest-sum-of-averages.js)
445452
- [Maximum Sum of 3 Non-Overlapping Subarrays](src/dynamic-programming/maximum-sum-of-3-non-overlapping-subarrays.js)
446453
- [Maximal Rectangle](src/dynamic-programming/maximal-rectangle.js)
454+
- [Min Cost Climbing Stairs](src/dynamic-programming/min-cost-climbing-stairs.js)
447455
- [House Robber](src/dynamic-programming/house-robber.js)
448456
- [House Robber II](src/dynamic-programming/house-robber-ii.js)
449457
- [Paint Fence](src/dynamic-programming/paint-fence.js)

src/array/candy-crush.js

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* Candy Crush
3+
*
4+
* This question is about implementing a basic elimination algorithm for Candy Crush.
5+
*
6+
* Given a 2D integer array board representing the grid of candy, different positive integers board[i][j]
7+
* represent different types of candies. A value of board[i][j] = 0 represents that the cell at position (i, j)
8+
* is empty. The given board represents the state of the game following the player's move.
9+
*
10+
* Now, you need to restore the board to a stable state by crushing candies according to the following rules:
11+
*
12+
* If three or more candies of the same type are adjacent vertically or horizontally, "crush" them all at the
13+
* same time - these positions become empty.
14+
*
15+
* After crushing all candies simultaneously, if an empty space on the board has candies on top of itself,
16+
* then these candies will drop until they hit a candy or bottom at the same time. (No new candies will drop
17+
* outside the top boundary.)
18+
*
19+
* After the above steps, there may exist more candies that can be crushed. If so, you need to repeat the above steps.
20+
*
21+
* If there does not exist more candies that can be crushed (ie. the board is stable), then return the current board.
22+
* You need to perform the above rules until the board becomes stable, then return the current board.
23+
*
24+
* Note:
25+
* The length of board will be in the range [3, 50].
26+
* The length of board[i] will be in the range [3, 50].
27+
* Each board[i][j] will initially start as an integer in the range [1, 2000].
28+
*/
29+
30+
/**
31+
* @param {number[][]} board
32+
* @return {number[][]}
33+
*/
34+
const candyCrush = board => {
35+
const m = board.length;
36+
const n = board[0].length;
37+
38+
let shouldContinue = false;
39+
40+
// Crush horizontally
41+
for (let i = 0; i < m; i++) {
42+
for (let j = 0; j < n - 2; j++) {
43+
const v = Math.abs(board[i][j]);
44+
if (v && v === Math.abs(board[i][j + 1]) && v === Math.abs(board[i][j + 2])) {
45+
board[i][j] = board[i][j + 1] = board[i][j + 2] = -v;
46+
shouldContinue = true;
47+
}
48+
}
49+
}
50+
51+
// Crush vertically
52+
for (let i = 0; i < m - 2; i++) {
53+
for (let j = 0; j < n; j++) {
54+
const v = Math.abs(board[i][j]);
55+
if (v && v === Math.abs(board[i + 1][j]) && v === Math.abs(board[i + 2][j])) {
56+
board[i][j] = board[i + 1][j] = board[i + 2][j] = -v;
57+
shouldContinue = true;
58+
}
59+
}
60+
}
61+
62+
// Drop vertically
63+
for (let j = 0; j < n; j++) {
64+
let row = m - 1;
65+
for (let i = m - 1; i >= 0; i--) {
66+
if (board[i][j] >= 0) {
67+
board[row--][j] = board[i][j];
68+
}
69+
}
70+
for (let i = row; i >= 0; i--) {
71+
board[i][j] = 0;
72+
}
73+
}
74+
75+
return shouldContinue ? candyCrush(board) : board;
76+
};
77+
78+
export { candyCrush };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Find All Duplicates in an Array
3+
*
4+
* Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
5+
*
6+
* Find all the elements that appear twice in this array.
7+
*
8+
* Could you do it without extra space and in O(n) runtime?
9+
*
10+
* Example:
11+
*
12+
* Input:
13+
* [4,3,2,7,8,2,3,1]
14+
*
15+
* Output:
16+
* [2,3]
17+
*/
18+
19+
/**
20+
* @param {number[]} nums
21+
* @return {number[]}
22+
*/
23+
const findDuplicates = nums => {
24+
const result = [];
25+
26+
for (let i = 0; i < nums.length; i++) {
27+
const index = Math.abs(nums[i]) - 1;
28+
29+
if (nums[index] < 0) {
30+
result.push(Math.abs(nums[i]));
31+
} else {
32+
nums[index] = -nums[index];
33+
}
34+
}
35+
36+
return result;
37+
};
38+
39+
export { findDuplicates };

src/array/maximum-swap.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Maximum Swap
3+
*
4+
* Given a non-negative integer, you could swap two digits at most once to get the maximum valued number.
5+
* Return the maximum valued number you could get.
6+
*
7+
* Example 1:
8+
*
9+
* Input: 2736
10+
* Output: 7236
11+
* Explanation: Swap the number 2 and the number 7.
12+
*
13+
* Example 2:
14+
*
15+
* Input: 9973
16+
* Output: 9973
17+
* Explanation: No swap.
18+
*/
19+
20+
/**
21+
* @param {number} num
22+
* @return {number}
23+
*/
24+
const maximumSwap = num => {
25+
const digits = num.toString().split('');
26+
27+
// Use buckets to record the last position of digit 0 ~ 9 in this num.
28+
const buckets = Array(10).fill(-1);
29+
for (let i = 0; i < digits.length; i++) {
30+
buckets[digits[i] - '0'] = i;
31+
}
32+
33+
// Loop through the num array from left to right. For each position,
34+
// we check whether there exists a larger digit in this num (start from 9 to current digit).
35+
// We also need to make sure the position of this larger digit is behind the current one.
36+
// If we find it, simply swap these two digits and return the result.
37+
for (let i = 0; i < digits.length; i++) {
38+
for (let k = 9; k > digits[i] - '0'; k--) {
39+
if (buckets[k] > i) {
40+
[digits[i], digits[buckets[k]]] = [digits[buckets[k]], digits[i]];
41+
return parseInt(digits.join(''));
42+
}
43+
}
44+
}
45+
46+
return num;
47+
};
48+
49+
export { maximumSwap };
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Split Array with Equal Sum
3+
*
4+
* Given an array with n integers, you need to find if there are triplets (i, j, k) which satisfies
5+
* following conditions:
6+
*
7+
* 0 < i, i + 1 < j, j + 1 < k < n - 1
8+
*
9+
* Sum of subarrays (0, i - 1), (i + 1, j - 1), (j + 1, k - 1) and (k + 1, n - 1) should be equal.
10+
* where we define that subarray (L, R) represents a slice of the original array starting from the element
11+
* indexed L to the element indexed R.
12+
*
13+
* Example:
14+
*
15+
* Input: [1,2,1,2,1,2,1]
16+
* Output: True
17+
*
18+
* Explanation:
19+
*
20+
* i = 1, j = 3, k = 5.
21+
* sum(0, i - 1) = sum(0, 0) = 1
22+
* sum(i + 1, j - 1) = sum(2, 2) = 1
23+
* sum(j + 1, k - 1) = sum(4, 4) = 1
24+
* sum(k + 1, n - 1) = sum(6, 6) = 1
25+
*
26+
* Note:
27+
* 1 <= n <= 2000.
28+
* Elements in the given array will be in range [-1,000,000, 1,000,000].
29+
*/
30+
31+
/**
32+
* @param {number[]} nums
33+
* @return {boolean}
34+
*/
35+
const splitArray = nums => {
36+
if (nums.length < 7) {
37+
return false;
38+
}
39+
40+
// Step 1. Calculate the prefix sum
41+
const sum = Array(nums.length).fill(0);
42+
sum[0] = nums[0];
43+
for (let i = 1; i < nums.length; i++) {
44+
sum[i] = sum[i - 1] + nums[i];
45+
}
46+
47+
// Here j is used for middle cut, i for left cut and k for right cut.
48+
// Iterate middle cuts and then find left cuts which divides the first
49+
// half into two equal quarters, store that quarter sums in the hashset.
50+
// Then find right cuts which divides the second half into two equal
51+
// quarters and check if quarter sum is present in the hashset.
52+
// If yes return true.
53+
for (let j = 3; j < nums.length - 3; j++) {
54+
const set = new Set();
55+
56+
for (let i = 1; i < j - 1; i++) {
57+
if (sum[i - 1] == sum[j - 1] - sum[i]) {
58+
set.add(sum[i - 1]);
59+
}
60+
}
61+
62+
for (let k = j + 2; k < nums.length - 1; k++) {
63+
if (sum[nums.length - 1] - sum[k] == sum[k - 1] - sum[j] && set.has(sum[k - 1] - sum[j])) {
64+
return true;
65+
}
66+
}
67+
}
68+
69+
return false;
70+
};
71+
72+
export { splitArray };

src/array/third-maximum-number.js

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Third Maximum Number
3+
*
4+
* Given a non-empty array of integers, return the third maximum number in this array.
5+
* If it does not exist, return the maximum number. The time complexity must be in O(n).
6+
*
7+
* Example 1:
8+
*
9+
* Input: [3, 2, 1]
10+
*
11+
* Output: 1
12+
*
13+
* Explanation: The third maximum is 1.
14+
*
15+
* Example 2:
16+
*
17+
* Input: [1, 2]
18+
*
19+
* Output: 2
20+
*
21+
* Explanation: The third maximum does not exist, so the maximum (2) is returned instead.
22+
*
23+
* Example 3:
24+
*
25+
* Input: [2, 2, 3, 1]
26+
*
27+
* Output: 1
28+
*
29+
* Explanation: Note that the third maximum here means the third maximum distinct number.
30+
* Both numbers with value 2 are both considered as second maximum.
31+
*/
32+
33+
/**
34+
* @param {number[]} nums
35+
* @return {number}
36+
*/
37+
const thirdMax = nums => {
38+
let first = -Infinity;
39+
let second = -Infinity;
40+
let third = -Infinity;
41+
42+
for (let num of nums) {
43+
if (num === first || num === second || num === third) {
44+
continue;
45+
}
46+
47+
if (num > first) {
48+
third = second;
49+
second = first;
50+
first = num;
51+
} else if (num > second) {
52+
third = second;
53+
second = num;
54+
} else if (num > third) {
55+
third = num;
56+
}
57+
}
58+
59+
return third === -Infinity ? first : third;
60+
};
61+
62+
export { thirdMax };

0 commit comments

Comments
 (0)