Skip to content

2025/05/09 #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions Hard/312 Burst Balloons.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 312. Burst Balloons

## Intuition

The key insight is to think about the problem in reverse: instead of bursting balloons one by one, we can think about adding balloons back one by one. For each step, we consider which balloon to add last.

## Approach

1. Add two dummy balloons with value 1 at the beginning and end of the array.
2. Define `dp[left][right]` as the maximum coins that can be collected by bursting all balloons between indices left and right (exclusive).
3. For each subproblem of length, we try each balloon (at position tmp) as the last one to burst.
4. The recurrence relation is:
`dp[left][right] = max(dp[left][right], dp[left][tmp] + dp[tmp][right] + nums[left] * nums[tmp] * nums[right])`
5. The final answer is `dp[0][n+1]`, representing the maximum coins obtained by bursting all original balloons.

## Complexity

- Time complexity: O(n³)
- Space complexity: O(n²)

## Keywords

- Dynamic Programming
- Interval DP

## Code

```go
func maxCoins(nums []int) int {
nums = append([]int{1}, nums...)
nums = append(nums, 1)

dp := make([][]int, len(nums))
for i := range dp {
dp[i] = make([]int, len(nums))
}

for length := 2; length < len(nums); length += 1 {
for left := 0; left < len(nums) - length; left += 1 {
right := left + length
for tmp := left + 1; tmp < right; tmp += 1 {
dp[left][right] = max(dp[left][right], dp[left][tmp] + dp[tmp][right] + nums[left] * nums[tmp] * nums[right])
}
}
}

return dp[0][len(nums) - 1]
}
```
46 changes: 46 additions & 0 deletions Hard/887 Super Egg Drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 887. Super Egg Drop

## Intuition

The traditional approach using dynamic programming with states (eggs, floors) leads to O(K*N²) complexity, which is too slow. Instead, we can reformulate the problem: if we have K eggs and can make M moves, what's the maximum number of floors we can cover?

## Approach

For each move, we have two possibilities when dropping an egg from a floor:

1. The egg breaks, so we can only use K-1 eggs for floors below
2. The egg doesn't break, so we can use K eggs for floors above

We use a mathematical recursion to calculate the maximum floors we can cover with K eggs and M moves:

- Let maxFloor[i] represent the maximum number of floors that can be determined with i eggs and current number of moves
- For each move, we update maxFloor[i] = 1 + maxFloor[i-1] + maxFloor[i]
- maxFloor[i-1]: floors covered if egg breaks
- maxFloor[i]: floors covered if egg doesn't break
- +1: the current floor we're dropping from

We keep increasing the number of moves until the maximum floor we can check is greater than or equal to N.

## Complexity

- Time complexity: O(K log N)
- Space complexity: O(K)

## Keywords

- Dynamic Programming

## Code

```go
func superEggDrop(k int, n int) int {
maxFloor := make([]int, k + 1)
m := 0
for ; maxFloor[k] < n; m += 1 {
for i := k; i > 0; i -= 1 {
maxFloor[i] = 1 + maxFloor[i - 1] + maxFloor[i]
}
}
return m
}
```
2 changes: 1 addition & 1 deletion Medium/416 Partition Equal Subset Sum.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ func canPartition(nums []int) bool {
}
return dp[sum]
}
```
```
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
| 210 | Course Schedule II | [go](/Medium/210%20Course%20Schedule%20II.md) | M |
| 236 | Lowest Common Ancestor of a Binary Tree | [go](/Medium/236%20Lowest%20Common%20Ancestor%20of%20a%20Binary%20Tree.md) | M |
| 239 | Sliding Window Maximum | [go](/Hard/239%20Sliding%20Window%20Maximum.md) | H |
| 312 | Burst Balloons | [go](/Hard/312%20Burst%20Balloons.md) | H |
| 322 | Coin Change | [go](/Medium/322%20Coin%20Change.md) | M |
| 416 | Partition Equal Subset Sum | [go](/Medium/416%20Partition%20Equal%20Subset%20Sum.md) | M |
| 435 | Non-overlapping Interval | [go](/Medium/435%20Non-overlapping%20Intervals.md) | M |
Expand All @@ -44,6 +45,7 @@
| 855 | Exam Room | [go](/Medium/855%20Exam%20Room.md) | M |
| 875 | Koko Eating Bananas | [go](/Medium/875%20Koko%20Eating%20Bananas.md) | M |
| 881 | Boats to Save People | [go](/Medium/881%20Boats%20to%20Save%20People.md) | M |
| 887 | Super Egg Drop | [go](/Hard/887%20Super%20Egg%20Drop.md) | H |
| 912 | Sort an Array | [go](/Medium/912%20Sort%20an%20Array.md) | M |
| 948 | Bag of Tokens | [go](/Medium/948%20Bag%20Of%20Tokens.md) | M |
| 1395 | Count Number of Trams | [go](/Medium/1395%20Count%20Number%20of%20Teams.md) | M |
Expand Down
Binary file added Week12/312 AC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 49 additions & 0 deletions Week12/312 Burst Balloons.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 312. Burst Balloons

## Intuition

The key insight is to think about the problem in reverse: instead of bursting balloons one by one, we can think about adding balloons back one by one. For each step, we consider which balloon to add last.

## Approach

1. Add two dummy balloons with value 1 at the beginning and end of the array.
2. Define `dp[left][right]` as the maximum coins that can be collected by bursting all balloons between indices left and right (exclusive).
3. For each subproblem of length, we try each balloon (at position tmp) as the last one to burst.
4. The recurrence relation is:
`dp[left][right] = max(dp[left][right], dp[left][tmp] + dp[tmp][right] + nums[left] * nums[tmp] * nums[right])`
5. The final answer is `dp[0][n+1]`, representing the maximum coins obtained by bursting all original balloons.

## Complexity

- Time complexity: O(n³)
- Space complexity: O(n²)

## Keywords

- Dynamic Programming
- Interval DP

## Code

```go
func maxCoins(nums []int) int {
nums = append([]int{1}, nums...)
nums = append(nums, 1)

dp := make([][]int, len(nums))
for i := range dp {
dp[i] = make([]int, len(nums))
}

for length := 2; length < len(nums); length += 1 {
for left := 0; left < len(nums) - length; left += 1 {
right := left + length
for tmp := left + 1; tmp < right; tmp += 1 {
dp[left][right] = max(dp[left][right], dp[left][tmp] + dp[tmp][right] + nums[left] * nums[tmp] * nums[right])
}
}
}

return dp[0][len(nums) - 1]
}
```
Binary file added Week12/416 AC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 69 additions & 0 deletions Week12/416 Partition Equal Subset Sum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# 416. Partition Equal Subset Sum

## Intuition

The problem can be transformed into finding if we can select some numbers from the array that sum up to half of the total sum. This is essentially a 0/1 knapsack problem where we need to determine if we can fill a knapsack of capacity sum/2 using the given numbers.

## Approach

1. First, calculate the total sum of the array
2. If the sum is odd, return false as equal partition is impossible
3. Divide the sum by 2 to get our target sum
4. Use dynamic programming to solve:
- Create a dp array where dp[j] represents if we can make sum j using the numbers
- For each number, we can either include it or not include it
- Use a temporary array to avoid affecting previous calculations
- If at any point we can make the target sum, return true
5. As an optimization, we also:
- Sort the array first
- Use binary search to check if target sum exists directly in array

## Complexity

- Time complexity: O(n * sum)
- Space complexity: O(sum)

## Keywords

- Dynamic Programming
- 0/1 Knapsack
- Binary Search

## Code

```go
func canPartition(nums []int) bool {
sum := 0
for _, num := range nums {
sum += num
}
if sum & 1 == 1 {
return false
}
sum >>= 1
sort.Ints(nums)
_, flag := slices.BinarySearch(nums, sum)
if flag {
return true
}
dp := make([]bool, sum + 1)
dp[0] = true
for _, num := range nums {
tmp := make([]bool, sum + 1)
tmp[0] = true
for j := 1; j <= sum ; j += 1 {
tmp[j] = dp[j]
if j >= num {
tmp[j] = (tmp[j] || dp[j - num])
}
}

if tmp[sum] {
return true
}

copy(dp, tmp)
}
return dp[sum]
}
```
Binary file added Week12/887 AC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions Week12/887 Super Egg Drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 887. Super Egg Drop

## Intuition

The traditional approach using dynamic programming with states (eggs, floors) leads to O(K*N²) complexity, which is too slow. Instead, we can reformulate the problem: if we have K eggs and can make M moves, what's the maximum number of floors we can cover?

## Approach

For each move, we have two possibilities when dropping an egg from a floor:

1. The egg breaks, so we can only use K-1 eggs for floors below
2. The egg doesn't break, so we can use K eggs for floors above

We use a mathematical recursion to calculate the maximum floors we can cover with K eggs and M moves:

- Let maxFloor[i] represent the maximum number of floors that can be determined with i eggs and current number of moves
- For each move, we update maxFloor[i] = 1 + maxFloor[i-1] + maxFloor[i]
- maxFloor[i-1]: floors covered if egg breaks
- maxFloor[i]: floors covered if egg doesn't break
- +1: the current floor we're dropping from

We keep increasing the number of moves until the maximum floor we can check is greater than or equal to N.

## Complexity

- Time complexity: O(K log N)
- Space complexity: O(K)

## Keywords

- Dynamic Programming

## Code

```go
func superEggDrop(k int, n int) int {
maxFloor := make([]int, k + 1)
m := 0
for ; maxFloor[k] < n; m += 1 {
for i := k; i > 0; i -= 1 {
maxFloor[i] = 1 + maxFloor[i - 1] + maxFloor[i]
}
}
return m
}
```