Boundary update without `+1` / `-1`
Wrong move: Setting `lo = mid` or `hi = mid` can stall and create an infinite loop.
Usually fails on: Two-element ranges never converge.
Fix: Use `lo = mid + 1` or `hi = mid - 1` where appropriate.
Move from brute-force thinking to an efficient approach using binary search strategy.
You are given an undirected connected graph with n nodes labeled from 0 to n - 1 and a 2D integer array edges where edges[i] = [ui, vi, wi] denotes an undirected edge between node ui and node vi with weight wi, and an integer k.
You are allowed to remove any number of edges from the graph such that the resulting graph has at most k connected components.
The cost of a component is defined as the maximum edge weight in that component. If a component has no edges, its cost is 0.
Return the minimum possible value of the maximum cost among all components after such removals.
Example 1:
Input: n = 5, edges = [[0,1,4],[1,2,3],[1,3,2],[3,4,6]], k = 2
Output: 4
Explanation:
Example 2:
Input: n = 4, edges = [[0,1,5],[1,2,5],[2,3,5]], k = 1
Output: 5
Explanation:
k = 1) requires the graph to stay fully connected.Constraints:
1 <= n <= 5 * 1040 <= edges.length <= 105edges[i].length == 30 <= ui, vi < n1 <= wi <= 1061 <= k <= nProblem summary: You are given an undirected connected graph with n nodes labeled from 0 to n - 1 and a 2D integer array edges where edges[i] = [ui, vi, wi] denotes an undirected edge between node ui and node vi with weight wi, and an integer k. You are allowed to remove any number of edges from the graph such that the resulting graph has at most k connected components. The cost of a component is defined as the maximum edge weight in that component. If a component has no edges, its cost is 0. Return the minimum possible value of the maximum cost among all components after such removals.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Binary Search · Union-Find
5 [[0,1,4],[1,2,3],[1,3,2],[3,4,6]] 2
4 [[0,1,5],[1,2,5],[2,3,5]] 1
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3613: Minimize Maximum Component Cost
class Solution {
private int[] p;
public int minCost(int n, int[][] edges, int k) {
if (k == n) {
return 0;
}
p = new int[n];
Arrays.setAll(p, i -> i);
Arrays.sort(edges, Comparator.comparingInt(a -> a[2]));
int cnt = n;
for (var e : edges) {
int u = e[0], v = e[1], w = e[2];
int pu = find(u), pv = find(v);
if (pu != pv) {
p[pu] = pv;
if (--cnt <= k) {
return w;
}
}
}
return 0;
}
private int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
}
// Accepted solution for LeetCode #3613: Minimize Maximum Component Cost
func minCost(n int, edges [][]int, k int) int {
p := make([]int, n)
for i := range p {
p[i] = i
}
var find func(int) int
find = func(x int) int {
if p[x] != x {
p[x] = find(p[x])
}
return p[x]
}
if k == n {
return 0
}
slices.SortFunc(edges, func(a, b []int) int {
return a[2] - b[2]
})
cnt := n
for _, e := range edges {
u, v, w := e[0], e[1], e[2]
pu, pv := find(u), find(v)
if pu != pv {
p[pu] = pv
if cnt--; cnt <= k {
return w
}
}
}
return 0
}
# Accepted solution for LeetCode #3613: Minimize Maximum Component Cost
class Solution:
def minCost(self, n: int, edges: List[List[int]], k: int) -> int:
def find(x: int) -> int:
if p[x] != x:
p[x] = find(p[x])
return p[x]
if k == n:
return 0
edges.sort(key=lambda x: x[2])
cnt = n
p = list(range(n))
for u, v, w in edges:
pu, pv = find(u), find(v)
if pu != pv:
p[pu] = pv
cnt -= 1
if cnt <= k:
return w
return 0
// Accepted solution for LeetCode #3613: Minimize Maximum Component Cost
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #3613: Minimize Maximum Component Cost
// class Solution {
// private int[] p;
//
// public int minCost(int n, int[][] edges, int k) {
// if (k == n) {
// return 0;
// }
// p = new int[n];
// Arrays.setAll(p, i -> i);
// Arrays.sort(edges, Comparator.comparingInt(a -> a[2]));
// int cnt = n;
// for (var e : edges) {
// int u = e[0], v = e[1], w = e[2];
// int pu = find(u), pv = find(v);
// if (pu != pv) {
// p[pu] = pv;
// if (--cnt <= k) {
// return w;
// }
// }
// }
// return 0;
// }
//
// private int find(int x) {
// if (p[x] != x) {
// p[x] = find(p[x]);
// }
// return p[x];
// }
// }
// Accepted solution for LeetCode #3613: Minimize Maximum Component Cost
function minCost(n: number, edges: number[][], k: number): number {
const p: number[] = Array.from({ length: n }, (_, i) => i);
const find = (x: number): number => {
if (p[x] !== x) {
p[x] = find(p[x]);
}
return p[x];
};
if (k === n) {
return 0;
}
edges.sort((a, b) => a[2] - b[2]);
let cnt = n;
for (const [u, v, w] of edges) {
const pu = find(u),
pv = find(v);
if (pu !== pv) {
p[pu] = pv;
if (--cnt <= k) {
return w;
}
}
}
return 0;
}
Use this to step through a reusable interview workflow for this problem.
Check every element from left to right until we find the target or exhaust the array. Each comparison is O(1), and we may visit all n elements, giving O(n). No extra space needed.
Each comparison eliminates half the remaining search space. After k comparisons, the space is n/2ᵏ. We stop when the space is 1, so k = log₂ n. No extra memory needed — just two pointers (lo, hi).
Review these before coding to avoid predictable interview regressions.
Wrong move: Setting `lo = mid` or `hi = mid` can stall and create an infinite loop.
Usually fails on: Two-element ranges never converge.
Fix: Use `lo = mid + 1` or `hi = mid - 1` where appropriate.