Skip to content

Commit 1525a39

Browse files
just4oncegitbook-bot
authored andcommitted
GitBook: [master] 3 pages modified
1 parent 739f521 commit 1525a39

File tree

3 files changed

+313
-0
lines changed

3 files changed

+313
-0
lines changed

SUMMARY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@
265265
* [852-peak-index-in-a-mountain-array](leetcode/binary-search/852-peak-index-in-a-mountain-array.md)
266266
* [862-shortest-subarray-with-sum-at-least-k](leetcode/binary-search/862-shortest-subarray-with-sum-at-least-k.md)
267267
* [875-koko-eating-bananas](leetcode/binary-search/875-koko-eating-bananas.md)
268+
* [878-nth-magical-number](leetcode/binary-search/878-nth-magical-number.md)
269+
* [887-super-egg-drop](leetcode/binary-search/887-super-egg-drop.md)
268270
* [dynamic-programing](leetcode/dynamic-programing/README.md)
269271
* [174-dungeon-game](leetcode/dynamic-programing/174-dungeon-game.md)
270272
* [bit-manipulation](leetcode/bit-manipulation-1/README.md)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# 878-nth-magical-number
2+
3+
## Question {#question}
4+
5+
[https://leetcode.com/problems/nth-magical-number/description/](https://leetcode.com/problems/nth-magical-number/description/)
6+
7+
A positive integer is _magical_ if it is divisible by either A or B.
8+
9+
Return the N-th magical number. Since the answer may be very large, **return it modulo** `10^9 + 7`.
10+
11+
1.
12+
**Example 1:**
13+
14+
```text
15+
Input: N = 1, A = 2, B = 3
16+
Output: 2
17+
```
18+
19+
**Example 2:**
20+
21+
```text
22+
Input: N = 4, A = 2, B = 3
23+
Output: 6
24+
```
25+
26+
**Example 3:**
27+
28+
```text
29+
Input: N = 5, A = 2, B = 4
30+
Output: 10
31+
```
32+
33+
**Example 4:**
34+
35+
```text
36+
Input: N = 3, A = 6, B = 4
37+
Output: 8
38+
```
39+
40+
**Note:**
41+
42+
1. `1 <= N <= 10^9`
43+
2. `2 <= A <= 40000`
44+
3. `2 <= B <= 40000`
45+
46+
## Thought Process {#thought-process}
47+
48+
1. Binary Search
49+
1. The magical number is always bounded between min\(A, B\) and min\(A, B\) \* N, lo and hi respectively
50+
2. Let's define A to be the smaller of two
51+
3. For every magical number, we count those numbers smaller than it and compare with N
52+
4. If we don't have enough count, we need to set lo = mi + 1
53+
5. Else hi = mi
54+
6. The count can be found by mi / A + mi / B - mi / L, where L is least common multiplier
55+
7. Time complexity O\(log\(N \* min\(A, B\)\)
56+
8. Space complexity O\(1\)
57+
2. Math
58+
1. If we make close observation on the number, we can see that the numbers appear in chunk
59+
2. For example, if A = 2, B = 3, \[2, 3, 4, 6\] -&gt; \[8, 9, 10, 12\] -&gt; \[14, 15, 16, 18\], where addition of LCM\(A, B\) to each of the element will be the next chunk
60+
3. So, if we can get the first sequence under the LCM\(A, B\), we can get the Nth number \(N - 1\) / L \* LCM + chunk\[\(N - 1\) % L\], where L = length of chunk and L = LCM / A + LCM / B - 1
61+
4. Time complexity O\(A +B\)
62+
5. Space complexity O\(1\)
63+
64+
## Solution
65+
66+
```java
67+
class Solution {
68+
public int nthMagicalNumber(int N, int A, int B) {
69+
if (A > B) return nthMagicalNumber(N, B, A);
70+
int M = (int) 1e9 + 7;
71+
if (B % A == 0) return (int) ((1L * A * N) % M);
72+
long L = A / gcd(A, B) * B;
73+
long lo = A, hi = lo * N;
74+
while (lo < hi) {
75+
long mi = lo + (hi - lo) / 2;
76+
long c = mi / A + mi / B - mi / L;
77+
if (c < N) lo = mi + 1;
78+
else hi = mi;
79+
}
80+
return (int) (lo % M);
81+
}
82+
83+
private int gcd (int a, int b) {
84+
if (b == 0) return a;
85+
return gcd(b, a % b);
86+
}
87+
}
88+
```
89+
90+
```java
91+
class Solution {
92+
public int nthMagicalNumber(int N, int A, int B) {
93+
int MOD = 1_000_000_007;
94+
int gcd = gcd(A, B), lcm = A * B / gcd;
95+
int L = lcm / A + lcm / B - 1;
96+
int c = (N - 1) / L , d = (N - 1) % L;
97+
long ans = (long) c * lcm;
98+
int[] nums = {A, B};
99+
for (int i = 0; i < d; i++) {
100+
if (nums[0] <= nums[1]) nums[0] += A;
101+
else nums[1] += B;
102+
}
103+
ans += Math.min(nums[0], nums[1]);
104+
return (int) (ans % MOD);
105+
}
106+
107+
private int gcd (int a, int b) {
108+
if (b == 0) return a;
109+
return gcd(b, a % b);
110+
}
111+
}
112+
```
113+
114+
## Additional {#additional}
115+
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# 887-super-egg-drop
2+
3+
## Question {#question}
4+
5+
[https://leetcode.com/problems/super-egg-drop/description/](https://leetcode.com/problems/super-egg-drop/description/)
6+
7+
You are given `K` eggs, and you have access to a building with `N` floors from `1` to `N`.
8+
9+
Each egg is identical in function, and if an egg breaks, you cannot drop it again.
10+
11+
You know that there exists a floor `F` with `0 <= F <= N` such that any egg dropped at a floor higher than `F` will break, and any egg dropped at or below floor `F` will not break.
12+
13+
Each _move_, you may take an egg \(if you have an unbroken one\) and drop it from any floor `X` \(with `1 <= X <= N`\).
14+
15+
Your goal is to know **with certainty** what the value of `F` is.
16+
17+
What is the minimum number of moves that you need to know with certainty what `F` is, regardless of the initial value of `F`?
18+
19+
**Example 1:**
20+
21+
```text
22+
Input: K = 1, N = 2
23+
Output: 2
24+
Explanation:
25+
Drop the egg from floor 1. If it breaks, we know with certainty that F = 0.
26+
Otherwise, drop the egg from floor 2. If it breaks, we know with certainty that F = 1.
27+
If it didn't break, then we know with certainty F = 2.
28+
Hence, we needed 2 moves in the worst case to know what F is with certainty.
29+
```
30+
31+
**Example 2:**
32+
33+
```text
34+
Input: K = 2, N = 6
35+
Output: 3
36+
```
37+
38+
**Example 3:**
39+
40+
```text
41+
Input: K = 3, N = 14
42+
Output: 4
43+
```
44+
45+
**Note:**
46+
47+
1. `1 <= K <= 100`
48+
2. `1 <= N <= 10000`
49+
50+
## Thought Process {#thought-process}
51+
52+
1. Brute Force with DP \(TLE\)
53+
1. We create an dp array to store the best moves for each eggs and floors combination, where dp\[i\]\[j\] represents the moves for i eggs and j floors
54+
2. For current eggs and floors, the best moves is obtained by dropping the egg from 1st floor up to current floor
55+
3. The minimum of all these drop tests are our answer
56+
4. For each test on ith floor, ranges from 1 to current floor, the egg could either break, so we need to use less egg on remaining floor dp\[curEgg - 1\]\[i - 1\], or it doesn't, so we use dp\[curEgg\]\[curFloor - i\]
57+
5. Because we are expecting worst case, the maximum of them + 1 \(current egg drop\) is the answer for dropping at ith floor
58+
6. Time complexity O\(KN^2\)
59+
7. Space complexity O\(KN\)
60+
2. DP with Binary
61+
1. Notice the function dp\( K - 1, i - 1\) increases when i increase, while on the other hand, dp\(K, N - i\) decreases when i increase
62+
2. We can use this observation to speed up the search for minimum i
63+
3. Time complexity O\(KNlogN\)
64+
4. Space complexity O\(KN\)
65+
3. DP with Optimality
66+
1. Looking at second function, the value increase when N increase, where the i\_opt \(current optimal\) can be use as the starting point for next N
67+
2. Time complexity O\(KN\)
68+
3. Space complexity O\(KN\)
69+
4. DP with Problem Rephrase
70+
1. Instead of asking how many moves, we rephrase the question into how many floor we can cover for m moves, and K egg
71+
2. We create dp array, where dp\[m\]\[k\] stores the floors that we can cover using m moves and k eggs
72+
3. For a floor X, when we drop the egg, there are two cases happen here
73+
4. If the egg breaks, we need to go down to check dp\[m - 1\]\[k - 1\], we cover dp\[m - 1\]\[k - 1\] + 1 + Y \(top of X\) floors
74+
5. Else If the egg doesn't break, we go up and check dp\[m - 1\]\[k\], we cover X + dp\[m -1\]\[k\] floors
75+
6. Where we can summarize into dp\[m\]\[k\] = dp\[m - 1\]\[k - 1\] + dp\[m - 1\]\[k\] + 1
76+
7. Time complexity O\(KlogN\)
77+
8. Space complexity O\(KN\)
78+
5. DP above - 1D
79+
1. We can reduce the space to O\(k\)
80+
2. Since dp\[m\]\[k\] depends on the last row only, we can use dp\[K+1\] to store all the information
81+
3. Instead going from forward, we need to travel from backward in order to avoid using the updated value
82+
4. Time complexity O\(KlogN\)
83+
5. Space complexity O\(K\)
84+
85+
## Solution
86+
87+
```java
88+
class Solution {
89+
public int superEggDrop(int K, int N) {
90+
int[][] memo = new int[K + 1][N + 1];
91+
// define memo[i][j] to be the number of moves for i eggs and j floors
92+
return dp(memo, K, N);
93+
}
94+
95+
private int dp(int[][] memo, int K, int N) {
96+
if (N <= 1) return 1;
97+
if (K == 1) return N;
98+
if (memo[K][N] > 0) return memo[K][N];
99+
// now for current K and N, the problem can break down into dropping eggs
100+
// from i = [1, N] floors.
101+
// For each floor, the egg either breaks so we use less egg for remaining floor
102+
// dp[K - 1][i - 1] or it doesn't that we use dp[K][N - i]. For each case, we
103+
// are expecting the worst cast, so the max of them + 1 will be compared with
104+
// current answer;
105+
int res = Integer.MAX_VALUE;
106+
for (int i = 1; i <= N; i++) {
107+
res = Math.min(res, Math.max(dp(memo, K - 1, i - 1), dp(memo, K, N - i)) + 1);
108+
}
109+
memo[K][N] = res;
110+
return res;
111+
}
112+
}
113+
```
114+
115+
```java
116+
class Solution {
117+
public int superEggDrop(int K, int N) {
118+
int[][] memo = new int[K + 1][N + 1];
119+
// define memo[i][j] to be the number of moves for i eggs and j floors
120+
return dp(memo, K, N);
121+
}
122+
123+
private int dp(int[][] memo, int K, int N) {
124+
if (N <= 1) return 1;
125+
if (K == 1) return N;
126+
if (memo[K][N] > 0) return memo[K][N];
127+
int res = N;
128+
int lo = 1, hi = N;
129+
while (lo < hi) {
130+
int mi = lo + (hi - lo) / 2;
131+
int breakMove = dp(memo, K - 1, mi - 1);
132+
int safeMove = dp(memo, K, N - mi);
133+
res = Math.min(res, Math.max(breakMove, safeMove) + 1);
134+
if (breakMove == safeMove) break;
135+
else if (breakMove > safeMove) hi = mi;
136+
else lo = mi + 1;
137+
}
138+
memo[K][N] = res;
139+
return res;
140+
}
141+
}
142+
```
143+
144+
```java
145+
class Solution {
146+
public int superEggDrop(int K, int N) {
147+
int[][] dp = new int[K + 1][N + 1];
148+
for (int j = 1; j <= N; j++) {
149+
dp[1][j] = j;
150+
}
151+
for (int k = 2; k <= K; k++) {
152+
int x = 1;
153+
for (int n = 1; n <= N; n++) {
154+
while (x < n && Math.max(dp[k - 1][x - 1], dp[k][n - x]) > Math.max(dp[k -1][x], dp[k][n - x -1])) x++;
155+
dp[k][n] = 1 + Math.max(dp[k - 1][x - 1], dp[k][n - x]);
156+
}
157+
}
158+
return dp[K][N];
159+
}
160+
}
161+
```
162+
163+
```text
164+
class Solution {
165+
public int superEggDrop(int K, int N) {
166+
int[][] dp = new int[N + 1][K + 1];
167+
int m = 0;
168+
while (dp[m][K] < N) {
169+
m++;
170+
for (int k = 1; k <= K; k++) {
171+
dp[m][k] = dp[m - 1][k - 1] + dp[m - 1][k] + 1;
172+
}
173+
}
174+
return m;
175+
}
176+
}
177+
```
178+
179+
```java
180+
class Solution {
181+
public int superEggDrop(int K, int N) {
182+
int[] dp = new int[K + 1];
183+
int m = 0;
184+
while (dp[K] < N) {
185+
m++;
186+
for (int k = K; k > 0; k--) {
187+
dp[k] += dp[k - 1] + 1;
188+
}
189+
}
190+
return m;
191+
}
192+
}
193+
```
194+
195+
## Additional {#additional}
196+

0 commit comments

Comments
 (0)