Skip to content
Open
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
53 changes: 53 additions & 0 deletions problems/2126-destroying-asteroids/analysis_daily_20260531.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 2126. Destroying Asteroids

[LeetCode Link](https://leetcode.com/problems/destroying-asteroids/)

Difficulty: Medium
Topics: Array, Greedy, Sorting
Acceptance Rate: 55.9%

## Hints

### Hint 1

You are allowed to pick any order. When you have full freedom over ordering and you want to maximize your chances of "surviving" each step, think about what kind of strategy almost always pays off in problems like this: **greedy**. Ask yourself, "If I have to face every asteroid eventually, which one should I face first?"

### Hint 2

A larger asteroid only becomes destroyable after the planet has absorbed enough mass from smaller ones. That suggests a particular ordering of the asteroids before you start simulating the collisions. What does that ordering look like, and what operation on the array gives it to you in one step?

### Hint 3

Sort `asteroids` in non-decreasing order, then walk through them once. If the current planet mass is ever smaller than the asteroid in front of you, you can return `false` immediately — no later ordering can rescue you because every earlier asteroid is already smaller. Otherwise, absorb the asteroid and keep going. Watch for overflow: the cumulative mass can grow well past `10^5`.

## Approach

The key observation is that if you ever survive a collision with asteroid `a`, you only gain mass — you never get weaker. So the optimal strategy is to face the smallest asteroid you can destroy next, growing your mass as much as possible before encountering larger asteroids.

This translates to a clean greedy algorithm:

1. Sort `asteroids` in non-decreasing order.
2. Iterate through the sorted array. For each asteroid `a`:
- If `mass < a`, return `false`. There is no way to handle `a` later because every remaining asteroid is `>= a` and contributes nothing to overcoming this barrier.
- Otherwise, set `mass += a` and continue.
3. If we finish the loop, every asteroid was destroyed; return `true`.

**Why it works:** Suppose some non-sorted order succeeds. Consider the first asteroid `a` in the sorted order where the sorted strategy fails. By that point in the sorted strategy, the planet has accumulated the sum of all asteroids strictly smaller than `a`. Any order that destroys `a` must have already absorbed at least enough mass to match `a`, but it cannot have absorbed more than the sum of all asteroids smaller than `a` before reaching `a` (since asteroids `>= a` cannot be tackled before `a`). So the sorted approach has the maximum possible mass available at the moment of facing `a` — if even that is not enough, no order works.

**Example (`mass = 10`, `asteroids = [3, 9, 19, 5, 21]`):**
After sorting: `[3, 5, 9, 19, 21]`. Trace: `10 → 13 → 18 → 27 → 46 → 67`. All survived → `true`.

**Overflow note:** With `asteroids.length` up to `10^5` and each value up to `10^5`, the running mass can reach up to `10^10 + 10^5`, which overflows `int32` but fits comfortably in Go's 64-bit `int`.

## Complexity Analysis

Time Complexity: O(n log n) for sorting, plus O(n) for the linear sweep.
Space Complexity: O(1) extra space (Go's `sort.Ints` sorts in place; ignoring the O(log n) recursion stack from the sort implementation).

## Edge Cases

- **Single asteroid that is too heavy** (e.g., `mass = 1`, `asteroids = [2]`): The very first comparison must fail and return `false`.
- **Single asteroid that exactly equals mass**: The constraint is `>=`, so equal mass destroys the asteroid. Make sure the comparison is `mass < a`, not `mass <= a`.
- **All asteroids smaller than initial mass**: Should always return `true` regardless of order.
- **Large cumulative mass / overflow**: Up to `10^5` asteroids of value `10^5` each pushes the running mass past `int32` range — use `int` (64-bit on standard Go platforms) to be safe.
- **Strictly increasing asteroid sequence requiring exact greedy ordering** (e.g., `mass = 5`, `asteroids = [5, 10, 20]`): Sorted order succeeds; tackling `10` before `5` would fail. This confirms sorting is essential.
59 changes: 59 additions & 0 deletions problems/2126-destroying-asteroids/problem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
number: "2126"
frontend_id: "2126"
title: "Destroying Asteroids"
slug: "destroying-asteroids"
difficulty: "Medium"
topics:
- "Array"
- "Greedy"
- "Sorting"
acceptance_rate: 5589.7
is_premium: false
created_at: "2026-05-31T04:58:08.647945+00:00"
fetched_at: "2026-05-31T04:58:08.647945+00:00"
link: "https://leetcode.com/problems/destroying-asteroids/"
date: "2026-05-31"
---

# 2126. Destroying Asteroids

You are given an integer `mass`, which represents the original mass of a planet. You are further given an integer array `asteroids`, where `asteroids[i]` is the mass of the `ith` asteroid.

You can arrange for the planet to collide with the asteroids in **any arbitrary order**. If the mass of the planet is **greater than or equal to** the mass of the asteroid, the asteroid is **destroyed** and the planet **gains** the mass of the asteroid. Otherwise, the planet is destroyed.

Return `true` _if**all** asteroids can be destroyed. Otherwise, return _`false` _._



**Example 1:**


**Input:** mass = 10, asteroids = [3,9,19,5,21]
**Output:** true
**Explanation:** One way to order the asteroids is [9,19,5,3,21]:
- The planet collides with the asteroid with a mass of 9. New planet mass: 10 + 9 = 19
- The planet collides with the asteroid with a mass of 19. New planet mass: 19 + 19 = 38
- The planet collides with the asteroid with a mass of 5. New planet mass: 38 + 5 = 43
- The planet collides with the asteroid with a mass of 3. New planet mass: 43 + 3 = 46
- The planet collides with the asteroid with a mass of 21. New planet mass: 46 + 21 = 67
All asteroids are destroyed.


**Example 2:**


**Input:** mass = 5, asteroids = [4,9,23,4]
**Output:** false
**Explanation:**
The planet cannot ever gain enough mass to destroy the asteroid with a mass of 23.
After the planet destroys the other asteroids, it will have a mass of 5 + 4 + 9 + 4 = 22.
This is less than 23, so a collision would not destroy the last asteroid.



**Constraints:**

* `1 <= mass <= 105`
* `1 <= asteroids.length <= 105`
* `1 <= asteroids[i] <= 105`
21 changes: 21 additions & 0 deletions problems/2126-destroying-asteroids/solution_daily_20260531.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

// Greedy: sort asteroids ascending, then absorb them in order.
// If the planet ever meets an asteroid larger than its current mass,
// no ordering can save it because every remaining asteroid is at least
// that size. Using int (64-bit) avoids overflow as cumulative mass
// can reach ~10^10.

import "sort"

func asteroidsDestroyed(mass int, asteroids []int) bool {
sort.Ints(asteroids)
planet := mass
for _, a := range asteroids {
if planet < a {
return false
}
planet += a
}
return true
}
92 changes: 92 additions & 0 deletions problems/2126-destroying-asteroids/solution_daily_20260531_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package main

import "testing"

func TestAsteroidsDestroyed(t *testing.T) {
tests := []struct {
name string
mass int
asteroids []int
expected bool
}{
{
name: "example 1: mass 10 vs [3,9,19,5,21] all destroyable",
mass: 10,
asteroids: []int{3, 9, 19, 5, 21},
expected: true,
},
{
name: "example 2: mass 5 vs [4,9,23,4] cannot reach 23",
mass: 5,
asteroids: []int{4, 9, 23, 4},
expected: false,
},
{
name: "edge case: single asteroid equal to mass (>= rule)",
mass: 5,
asteroids: []int{5},
expected: true,
},
{
name: "edge case: single asteroid heavier than mass",
mass: 1,
asteroids: []int{2},
expected: false,
},
{
name: "edge case: single asteroid lighter than mass",
mass: 100,
asteroids: []int{1},
expected: true,
},
{
name: "edge case: order matters - sorted greedy succeeds",
mass: 5,
asteroids: []int{5, 10, 20},
expected: true,
},
{
name: "edge case: all equal to initial mass",
mass: 3,
asteroids: []int{3, 3, 3, 3},
expected: true,
},
{
name: "edge case: large cumulative mass (overflow guard)",
mass: 100000,
asteroids: makeRepeated(100000, 100000),
expected: true,
},
{
name: "edge case: first asteroid already too heavy",
mass: 1,
asteroids: []int{2, 3, 4, 5},
expected: false,
},
{
name: "edge case: minimum mass barely survives chain",
mass: 1,
asteroids: []int{1, 2, 4, 8, 16},
expected: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
input := append([]int(nil), tt.asteroids...)
got := asteroidsDestroyed(tt.mass, input)
if got != tt.expected {
t.Errorf("asteroidsDestroyed(%d, %v) = %v, want %v",
tt.mass, tt.asteroids, got, tt.expected)
}
})
}
}

func makeRepeated(value, count int) []int {
out := make([]int, count)
for i := range out {
out[i] = value
}
return out
}