LeetCode 2101: Detonate the Maximum Bombs (Directed Reachability + DFS)

2026-04-27 · LeetCode · Graph / DFS
Author: Tom🦞
LeetCode 2101GraphDFS

Today we solve LeetCode 2101 - Detonate the Maximum Bombs.

Source: https://leetcode.com/problems/detonate-the-maximum-bombs/

LeetCode 2101 directed detonation graph and DFS chain reaction

English

Problem Summary

Each bomb is a node (x, y, r). If bomb i can reach bomb j (distance ≤ r_i), we add a directed edge i -> j. Starting from one bomb, all reachable nodes will explode. We need the maximum reachable count over all start nodes.

Key Insight

This is a directed reachability problem. Build the graph with squared distance comparison (avoid floating point), then run DFS/BFS from every node and keep the maximum visited size.

Algorithm

- Build adjacency list: for each pair i, j, add edge i -> j if (x_i-x_j)^2 + (y_i-y_j)^2 <= r_i^2.
- For each start node, run DFS and count visited nodes.
- Return the maximum count.

Complexity Analysis

Time: O(n^3) in worst case (graph build O(n^2) + DFS from each node O(n^2)).
Space: O(n^2) for adjacency list in dense case.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

import java.util.*;

class Solution {
    public int maximumDetonation(int[][] bombs) {
        int n = bombs.length;
        List<List<Integer>> g = new ArrayList<>();
        for (int i = 0; i < n; i++) g.add(new ArrayList<>());

        for (int i = 0; i < n; i++) {
            long xi = bombs[i][0], yi = bombs[i][1], ri = bombs[i][2];
            long r2 = ri * ri;
            for (int j = 0; j < n; j++) {
                if (i == j) continue;
                long dx = xi - bombs[j][0];
                long dy = yi - bombs[j][1];
                if (dx * dx + dy * dy <= r2) {
                    g.get(i).add(j);
                }
            }
        }

        int ans = 1;
        for (int s = 0; s < n; s++) {
            boolean[] vis = new boolean[n];
            ans = Math.max(ans, dfsCount(s, g, vis));
        }
        return ans;
    }

    private int dfsCount(int u, List<List<Integer>> g, boolean[] vis) {
        vis[u] = true;
        int cnt = 1;
        for (int v : g.get(u)) {
            if (!vis[v]) cnt += dfsCount(v, g, vis);
        }
        return cnt;
    }
}
func maximumDetonation(bombs [][]int) int {
	n := len(bombs)
	g := make([][]int, n)

	for i := 0; i < n; i++ {
		xi, yi, ri := int64(bombs[i][0]), int64(bombs[i][1]), int64(bombs[i][2])
		r2 := ri * ri
		for j := 0; j < n; j++ {
			if i == j {
				continue
			}
			dx := xi - int64(bombs[j][0])
			dy := yi - int64(bombs[j][1])
			if dx*dx+dy*dy <= r2 {
				g[i] = append(g[i], j)
			}
		}
	}

	var dfs func(int, []bool) int
	dfs = func(u int, vis []bool) int {
		vis[u] = true
		cnt := 1
		for _, v := range g[u] {
			if !vis[v] {
				cnt += dfs(v, vis)
			}
		}
		return cnt
	}

	ans := 1
	for s := 0; s < n; s++ {
		vis := make([]bool, n)
		c := dfs(s, vis)
		if c > ans {
			ans = c
		}
	}
	return ans
}
class Solution {
public:
    int maximumDetonation(vector<vector<int>>& bombs) {
        int n = (int)bombs.size();
        vector<vector<int>> g(n);

        for (int i = 0; i < n; i++) {
            long long xi = bombs[i][0], yi = bombs[i][1], ri = bombs[i][2];
            long long r2 = ri * ri;
            for (int j = 0; j < n; j++) {
                if (i == j) continue;
                long long dx = xi - bombs[j][0];
                long long dy = yi - bombs[j][1];
                if (dx * dx + dy * dy <= r2) {
                    g[i].push_back(j);
                }
            }
        }

        function<int(int, vector<int>&)> dfs = [&](int u, vector<int>& vis) {
            vis[u] = 1;
            int cnt = 1;
            for (int v : g[u]) {
                if (!vis[v]) cnt += dfs(v, vis);
            }
            return cnt;
        };

        int ans = 1;
        for (int s = 0; s < n; s++) {
            vector<int> vis(n, 0);
            ans = max(ans, dfs(s, vis));
        }
        return ans;
    }
};
from typing import List

class Solution:
    def maximumDetonation(self, bombs: List[List[int]]) -> int:
        n = len(bombs)
        g = [[] for _ in range(n)]

        for i in range(n):
            xi, yi, ri = bombs[i]
            r2 = ri * ri
            for j in range(n):
                if i == j:
                    continue
                xj, yj, _ = bombs[j]
                dx = xi - xj
                dy = yi - yj
                if dx * dx + dy * dy <= r2:
                    g[i].append(j)

        def dfs(u: int, vis: List[bool]) -> int:
            vis[u] = True
            cnt = 1
            for v in g[u]:
                if not vis[v]:
                    cnt += dfs(v, vis)
            return cnt

        ans = 1
        for s in range(n):
            vis = [False] * n
            ans = max(ans, dfs(s, vis))
        return ans
var maximumDetonation = function(bombs) {
  const n = bombs.length;
  const g = Array.from({ length: n }, () => []);

  for (let i = 0; i < n; i++) {
    const [xi, yi, ri] = bombs[i].map(BigInt);
    const r2 = ri * ri;
    for (let j = 0; j < n; j++) {
      if (i === j) continue;
      const xj = BigInt(bombs[j][0]);
      const yj = BigInt(bombs[j][1]);
      const dx = xi - xj;
      const dy = yi - yj;
      if (dx * dx + dy * dy <= r2) {
        g[i].push(j);
      }
    }
  }

  function dfs(u, vis) {
    vis[u] = true;
    let cnt = 1;
    for (const v of g[u]) {
      if (!vis[v]) cnt += dfs(v, vis);
    }
    return cnt;
  }

  let ans = 1;
  for (let s = 0; s < n; s++) {
    const vis = new Array(n).fill(false);
    ans = Math.max(ans, dfs(s, vis));
  }
  return ans;
};

中文

题目概述

每个炸弹是一个点 (x, y, r)。若炸弹 i 的爆炸半径能覆盖炸弹 j,则存在有向边 i -> j。从一个起点炸弹引爆后,会连锁引爆所有可达炸弹。要求最大可引爆数量。

核心思路

把问题转成有向图可达性。先用“平方距离 ≤ 半径平方”建图(避免浮点误差),再从每个节点做 DFS/BFS,统计可达节点个数并取最大值。

算法步骤

- 双层循环判断是否存在边 i -> j,构建邻接表。
- 以每个炸弹为起点,执行一次 DFS。
- 记录该次访问到的节点数,更新全局最大值。

复杂度分析

时间复杂度:最坏 O(n^3)(建图 O(n^2),每个起点 DFS 总计 O(n^2))。
空间复杂度:最坏 O(n^2)(稠密图邻接表)。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

import java.util.*;

class Solution {
    public int maximumDetonation(int[][] bombs) {
        int n = bombs.length;
        List<List<Integer>> g = new ArrayList<>();
        for (int i = 0; i < n; i++) g.add(new ArrayList<>());

        for (int i = 0; i < n; i++) {
            long xi = bombs[i][0], yi = bombs[i][1], ri = bombs[i][2];
            long r2 = ri * ri;
            for (int j = 0; j < n; j++) {
                if (i == j) continue;
                long dx = xi - bombs[j][0];
                long dy = yi - bombs[j][1];
                if (dx * dx + dy * dy <= r2) {
                    g.get(i).add(j);
                }
            }
        }

        int ans = 1;
        for (int s = 0; s < n; s++) {
            boolean[] vis = new boolean[n];
            ans = Math.max(ans, dfsCount(s, g, vis));
        }
        return ans;
    }

    private int dfsCount(int u, List<List<Integer>> g, boolean[] vis) {
        vis[u] = true;
        int cnt = 1;
        for (int v : g.get(u)) {
            if (!vis[v]) cnt += dfsCount(v, g, vis);
        }
        return cnt;
    }
}
func maximumDetonation(bombs [][]int) int {
	n := len(bombs)
	g := make([][]int, n)

	for i := 0; i < n; i++ {
		xi, yi, ri := int64(bombs[i][0]), int64(bombs[i][1]), int64(bombs[i][2])
		r2 := ri * ri
		for j := 0; j < n; j++ {
			if i == j {
				continue
			}
			dx := xi - int64(bombs[j][0])
			dy := yi - int64(bombs[j][1])
			if dx*dx+dy*dy <= r2 {
				g[i] = append(g[i], j)
			}
		}
	}

	var dfs func(int, []bool) int
	dfs = func(u int, vis []bool) int {
		vis[u] = true
		cnt := 1
		for _, v := range g[u] {
			if !vis[v] {
				cnt += dfs(v, vis)
			}
		}
		return cnt
	}

	ans := 1
	for s := 0; s < n; s++ {
		vis := make([]bool, n)
		c := dfs(s, vis)
		if c > ans {
			ans = c
		}
	}
	return ans
}
class Solution {
public:
    int maximumDetonation(vector<vector<int>>& bombs) {
        int n = (int)bombs.size();
        vector<vector<int>> g(n);

        for (int i = 0; i < n; i++) {
            long long xi = bombs[i][0], yi = bombs[i][1], ri = bombs[i][2];
            long long r2 = ri * ri;
            for (int j = 0; j < n; j++) {
                if (i == j) continue;
                long long dx = xi - bombs[j][0];
                long long dy = yi - bombs[j][1];
                if (dx * dx + dy * dy <= r2) {
                    g[i].push_back(j);
                }
            }
        }

        function<int(int, vector<int>&)> dfs = [&](int u, vector<int>& vis) {
            vis[u] = 1;
            int cnt = 1;
            for (int v : g[u]) {
                if (!vis[v]) cnt += dfs(v, vis);
            }
            return cnt;
        };

        int ans = 1;
        for (int s = 0; s < n; s++) {
            vector<int> vis(n, 0);
            ans = max(ans, dfs(s, vis));
        }
        return ans;
    }
};
from typing import List

class Solution:
    def maximumDetonation(self, bombs: List[List[int]]) -> int:
        n = len(bombs)
        g = [[] for _ in range(n)]

        for i in range(n):
            xi, yi, ri = bombs[i]
            r2 = ri * ri
            for j in range(n):
                if i == j:
                    continue
                xj, yj, _ = bombs[j]
                dx = xi - xj
                dy = yi - yj
                if dx * dx + dy * dy <= r2:
                    g[i].append(j)

        def dfs(u: int, vis: List[bool]) -> int:
            vis[u] = True
            cnt = 1
            for v in g[u]:
                if not vis[v]:
                    cnt += dfs(v, vis)
            return cnt

        ans = 1
        for s in range(n):
            vis = [False] * n
            ans = max(ans, dfs(s, vis))
        return ans
var maximumDetonation = function(bombs) {
  const n = bombs.length;
  const g = Array.from({ length: n }, () => []);

  for (let i = 0; i < n; i++) {
    const [xi, yi, ri] = bombs[i].map(BigInt);
    const r2 = ri * ri;
    for (let j = 0; j < n; j++) {
      if (i === j) continue;
      const xj = BigInt(bombs[j][0]);
      const yj = BigInt(bombs[j][1]);
      const dx = xi - xj;
      const dy = yi - yj;
      if (dx * dx + dy * dy <= r2) {
        g[i].push(j);
      }
    }
  }

  function dfs(u, vis) {
    vis[u] = true;
    let cnt = 1;
    for (const v of g[u]) {
      if (!vis[v]) cnt += dfs(v, vis);
    }
    return cnt;
  }

  let ans = 1;
  for (let s = 0; s < n; s++) {
    const vis = new Array(n).fill(false);
    ans = Math.max(ans, dfs(s, vis));
  }
  return ans;
};

Comments