Talentd
FleetCode
Make and follow sheets.Sign in

Cut Off Trees for Golf Event solution and explanation

HardArrayBreadth-First SearchHeap (Priority Queue)Matrix8 min read36.8% acceptanceUpdated 9 Apr 2026
花花酱 LeetCode 675. Cut Off Trees for Golf Event - 刷题找工作 EP55Hua Hua · 12:25 · 7K viewsWatch on YouTube
9 more videos on this problem
  1. 花花酱 LeetCode 675. Cut Off Trees for Golf Event - 刷题找工作 EP55Hua Hua · 12:25 · 7K views
  2. Leetcode 675(Hard) Cut Off Trees for Golf Event: Simple C++ SolutionShivam Patel · 26:37 · 6K views
  3. 675. Cut Off Trees for Golf Event | LEETCODE HARDcode Explainer · 10:52 · 3K views
  4. Leetcode 675. Cut Off Trees for Golf EventUnofficial Sendoh · 13:55 · 2K views
  5. Leetcode 675. Cut Off Trees for Golf EventAlgorithms for Big Bucks · 14:00 · 1K views
  6. 【每日一题】675. Cut Off Trees for Golf Event, 09/06/2019Huifeng Guan · 23:13 · 951 views
  7. Day 54/75: Problem Name: Cut Off Trees for Golf Event | Leetcode | #75DaysHardLeetcodeCodeInsanity · 6:31 · 513 views
  8. LeetCode 675 | Cut Off Trees for Golf Event | BFS | JavaSleepy Cracker · 18:25 · 282 views
  9. Leetcode 675. Cut Off Trees for Golf Event (bfs)LetsCode · 22:04 · 271 views
  10. Leetcode 0675. Cut Off Trees for Golf EventFearless Learner · 24:57 · 219 views

The problem

You are asked to cut off all the trees in a forest for a golf event. The forest is represented as an m x n matrix. In this matrix:

  • 0 means the cell cannot be walked through.
  • 1 represents an empty cell that can be walked through.
  • A number greater than 1 represents a tree in a cell that can be walked through, and this number is the tree's height.

In one step, you can walk in any of the four directions: north, east, south, and west. If you are standing in a cell with a tree, you can choose whether to cut it off.

You must cut off the trees in order from shortest to tallest. When you cut off a tree, the value at its cell becomes 1 (an empty cell).

Starting from the point (0, 0), return the minimum steps you need to walk to cut off all the trees. If you cannot cut off all the trees, return -1.

Note: The input is generated such that no two trees have the same height, and there is at least one tree needs to be cut off.

Example 1:

Input: forest = [[1,2,3],[0,0,4],[7,6,5]]
Output: 6
Explanation: Following the path above allows you to cut off the trees from shortest to tallest in 6 steps.

Example 2:

Input: forest = [[1,2,3],[0,0,0],[7,6,5]]
Output: -1
Explanation: The trees in the bottom row cannot be accessed as the middle row is blocked.

Example 3:

Input: forest = [[2,3,4],[0,0,5],[8,7,6]]
Output: 6
Explanation: You can follow the same path as Example 1 to cut off all the trees.
Note that you can cut off the first tree at (0, 0) before making any steps.

Constraints:

  • m == forest.length
  • n == forest[i].length
  • 1 <= m, n <= 50
  • 0 <= forest[i][j] <= 109
  • Heights of all trees are distinct.

Approach overview

Problem Overview: You are given a grid representing a forest. Cells contain obstacles (0), walkable ground (1), or trees with heights greater than 1. Starting at (0,0), you must cut all trees in increasing order of height while minimizing total steps. If any tree is unreachable, return -1.

Approach 1: BFS Shortest Path Between Trees (Time: O(T * m * n), Space: O(m * n))

The key idea is to cut trees strictly in increasing height order. First collect all tree cells and sort them by height (often using a heap or sorted list). Starting from (0,0), run BFS to compute the shortest path to the next tree. After reaching it, repeat BFS from that position to the next tree in sorted order. Each BFS explores the grid level-by-level using a queue and a visited set to avoid revisiting cells.

This works because the grid has uniform movement cost, so Breadth-First Search always finds the shortest path. Tree ordering can be managed with sorting or a Heap (Priority Queue). In the worst case you run BFS for every tree, giving O(T * m * n) time where T is the number of trees. The grid itself is a classic matrix traversal problem.

Approach 2: Bidirectional BFS for Optimal Path Finding (Time: O(T * m * n), Space: O(m * n))

Bidirectional BFS speeds up individual shortest-path searches by exploring from both the start and target tree simultaneously. Instead of expanding one frontier across the entire grid, two frontiers grow toward each other. When they meet, you have the shortest distance. This reduces the explored search space in practice, especially when trees are far apart.

The algorithm still processes trees in sorted height order, but each step uses two queues and two visited sets. The theoretical worst-case complexity remains O(T * m * n), but the constant factor is lower because each BFS explores fewer cells on average. This approach is useful when the forest grid is large and paths between trees are long.

Recommended for interviews: The standard BFS shortest-path approach is what most interviewers expect. It shows you recognize the grid as an unweighted graph and know how to combine sorting with repeated BFS searches. Bidirectional BFS is a strong optimization discussion if the interviewer asks about improving practical performance.

Approach 1: Breadth-First Search (BFS) for Shortest Path

This approach involves using a BFS algorithm to find the shortest path between the starting point and each tree in increasing order of their heights. We first list all trees with their positions and heights, sort them, and for each sorted tree, compute the shortest path using BFS. If any tree is unreachable, we return -1.

from typing import List
from collections import deque

class Solution:
    def cutOffTree(self, forest: List[List[int]]) -> int:
        def bfs(sr, sc, tr, tc):
            if sr == tr and sc == tc:
                return 0
            queue = deque([(sr, sc, 0)])
            visited = set((sr, sc))
            while queue:
                r, c, steps = queue.popleft()
                for dr, dc in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
                    nr, nc = r + dr, c + dc
                    if 0 <= nr < len(forest) and 0 <= nc < len(forest[0]) and (nr, nc) not in visited and forest[nr][nc] > 0:
                        if nr == tr and nc == tc:
                            return steps + 1
                        queue.append((nr, nc, steps + 1))
                        visited.add((nr, nc))
            return -1
        
        trees = sorted((height, r, c)
                       for r, row in enumerate(forest)
                       for c, height in enumerate(row)
                       if height > 1)
                       
        steps = 0
        sr = sc = 0
        for _, tr, tc in trees:
            s = bfs(sr, sc, tr, tc)
            if s == -1:
                return -1
            steps += s
            sr, sc = tr, tc
        return steps
import java.util.*;

class Solution {
    private static final int[][] DIRECTIONS = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    public int cutOffTree(List<List<Integer>> forest) {
        List<int[]> trees = new ArrayList<>();
        int rows = forest.size();
        int cols = forest.get(0).size();
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                int value = forest.get(r).get(c);
                if (value > 1) {
                    trees.add(new int[]{value, r, c});
                }
            }
        }
        trees.sort(Comparator.comparingInt(a -> a[0]));

        int sr = 0, sc = 0, totalSteps = 0;
        for (int[] tree : trees) {
            int tr = tree[1], tc = tree[2];
            int steps = bfs(forest, sr, sc, tr, tc);
            if (steps == -1) return -1;
            totalSteps += steps;
            sr = tr;
            sc = tc;
        }
        return totalSteps;
    }

    private int bfs(List<List<Integer>> forest, int sr, int sc, int tr, int tc) {
        if (sr == tr && sc == tc) return 0;
        int rows = forest.size();
        int cols = forest.get(0).size();
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{sr, sc});
        boolean[][] visited = new boolean[rows][cols];
        visited[sr][sc] = true;
        int steps = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int[] cur = queue.poll();
                int r = cur[0], c = cur[1];
                if (r == tr && c == tc) return steps;
                for (int[] d : DIRECTIONS) {
                    int nr = r + d[0], nc = c + d[1];
                    if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && !visited[nr][nc] && forest.get(nr).get(nc) > 0) {
                        visited[nr][nc] = true;
                        queue.offer(new int[]{nr, nc});
                    }
                }
            }
            steps++;
        }
        return -1;
    }
}
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

class Solution {
public:
    vector<vector<int>> directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    
    int bfs(vector<vector<int>>& forest, int sr, int sc, int tr, int tc) {
        int m = forest.size(), n = forest[0].size();
        queue<pair<int, int>> q;
        q.push({sr, sc});
        vector<vector<bool>> visited(m, vector<bool>(n, false));
        visited[sr][sc] = true;
        int steps = 0;
        while (!q.empty()) {
            int size = q.size();
            while (size--) {
                auto [r, c] = q.front(); q.pop();
                if (r == tr && c == tc) return steps;
                for (auto& dir : directions) {
                    int nr = r + dir[0], nc = c + dir[1];
                    if (nr >= 0 && nr < m && nc >= 0 && nc < n && !visited[nr][nc] && forest[nr][nc] > 0) {
                        visited[nr][nc] = true;
                        q.push({nr, nc});
                    }
                }
            }
            steps++;
        }
        return -1;
    }
    int cutOffTree(vector<vector<int>>& forest) {
        vector<vector<int>> trees;
        int m = forest.size(), n = forest[0].size();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (forest[i][j] > 1) trees.push_back({forest[i][j], i, j});
            }
        }
        sort(trees.begin(), trees.end());
        
        int sr = 0, sc = 0, total_steps = 0;
        for (auto& tree : trees) {
            int tr = tree[1], tc = tree[2];
            int steps = bfs(forest, sr, sc, tr, tc);
            if (steps == -1) return -1;
            total_steps += steps;
            sr = tr;
            sc = tc;
        }
        return total_steps;
    }
};
var cutOffTree = function(forest) {
    const directions = [[1, 0], [-1, 0], [0, 1], [0, -1]];
    const bfs = (sr, sc, tr, tc) => {
        if (sr === tr && sc === tc) return 0;
        const queue = [[sr, sc, 0]];
        const visited = new Set([`${sr},${sc}`]);
        while (queue.length) {
            const [r, c, steps] = queue.shift();
            for (const [dr, dc] of directions) {
                const nr = r + dr, nc = c + dc;
                if (nr >= 0 && nr < forest.length && nc >= 0 && nc < forest[0].length && !visited.has(`${nr},${nc}`) && forest[nr][nc] > 0) {
                    if (nr === tr && nc === tc) return steps + 1;
                    queue.push([nr, nc, steps + 1]);
                    visited.add(`${nr},${nc}`);
                }
            }
        }
        return -1;
    };

    const trees = [];
    for (let r = 0; r < forest.length; r++) {
        for (let c = 0; c < forest[0].length; c++) {
            if (forest[r][c] > 1) trees.push([forest[r][c], r, c]);
        }
    }
    trees.sort((a, b) => a[0] - b[0]);

    let totalSteps = 0;
    let sr = 0, sc = 0;
    for (const [height, tr, tc] of trees) {
        const steps = bfs(sr, sc, tr, tc);
        if (steps === -1) return -1;
        totalSteps += steps;
        sr = tr;
        sc = tc;
    }
    return totalSteps;
};
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>

// Define directions for moving in the grid
int directions[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

// Function prototypes
int bfs(int** forest, int m, int n, int sr, int sc, int tr, int tc);
int cmpfunc(const void* a, const void* b);

int cutOffTree(int** forest, int forestSize, int* forestColSize){
    int m = forestSize;
    int n = forestColSize[0];
    
    // Extract trees and sort by height
    int trees[m*n][3], count = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (forest[i][j] > 1) {
                trees[count][0] = forest[i][j];
                trees[count][1] = i;
                trees[count][2] = j;
                count++;
            }
        }
    }
    qsort(trees, count, sizeof(trees[0]), cmpfunc);
    
    // Start cutting trees
    int totalSteps = 0, sr = 0, sc = 0;
    for (int i = 0; i < count; i++) {
        int tr = trees[i][1];
        int tc = trees[i][2];
        int steps = bfs(forest, m, n, sr, sc, tr, tc);
        if (steps == -1) return -1;
        totalSteps += steps;
        sr = tr;
        sc = tc;
    }
    return totalSteps;
}

int bfs(int** forest, int m, int n, int sr, int sc, int tr, int tc) {
    if (sr == tr && sc == tc) return 0;
    bool visited[m][n];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            visited[i][j] = false;
        }
    }
    visited[sr][sc] = true;
    int queue[m*n][2];
    int front = 0, back = 0;
    queue[back][0] = sr;
    queue[back++][1] = sc;
    int steps = 0;
    while (front < back) {
        int size = back - front;
        steps++;
        for (int i = 0; i < size; i++) {
            int r = queue[front][0];
            int c = queue[front][1];
            front++;
            for (int d = 0; d < 4; d++) {
                int nr = r + directions[d][0];
                int nc = c + directions[d][1];
                if (nr >= 0 && nr < m && nc >= 0 && nc < n && !visited[nr][nc] && forest[nr][nc] > 0) {
                    if (nr == tr && nc == tc) return steps;
                    visited[nr][nc] = true;
                    queue[back][0] = nr;
                    queue[back++][1] = nc;
                }
            }
        }
    }
    return -1;
}

int cmpfunc(const void* a, const void* b) {
    int l = ((int*)a)[0];
    int r = ((int*)b)[0];
    return (l - r);
}
using System;
using System.Collections.Generic;

public class Solution {
    private static int[][] Directions = new int[4][] {
        new int[] {1, 0}, new int[] {-1, 0}, new int[] {0, 1}, new int[] {0, -1}
    };
    
    public int CutOffTree(IList<IList<int>> forest) {
        List<int[]> trees = new List<int[]>();
        int m = forest.Count, n = forest[0].Count;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (forest[i][j] > 1) {
                    trees.Add(new int[] { forest[i][j], i, j });
                }
            }
        }
        trees.Sort((a, b) => a[0] - b[0]);

        int sr = 0, sc = 0, totalSteps = 0;
        foreach (var tree in trees) {
            int tr = tree[1], tc = tree[2];
            int steps = BFS(forest, sr, sc, tr, tc);
            if (steps == -1) return -1;
            totalSteps += steps;
            sr = tr;
            sc = tc;
        }
        return totalSteps;
    }

    private int BFS(IList<IList<int>> forest, int sr, int sc, int tr, int tc) {
        if (sr == tr && sc == tc) return 0;
        int m = forest.Count, n = forest[0].Count;
        Queue<int[]> queue = new Queue<int[]>();
        queue.Enqueue(new int[] { sr, sc });
        bool[,] visited = new bool[m, n];
        visited[sr, sc] = true;
        int steps = 0;

        while (queue.Count > 0) {
            int size = queue.Count;
            while (size-- > 0) {
                var current = queue.Dequeue();
                int r = current[0], c = current[1];
                if (r == tr && c == tc) {
                    return steps;
                }
                foreach (var direction in Directions) {
                    int nr = r + direction[0], nc = c + direction[1];
                    if (nr >= 0 && nr < m && nc >= 0 && nc < n && !visited[nr, nc] && forest[nr][nc] > 0) {
                        visited[nr, nc] = true;
                        queue.Enqueue(new int[] { nr, nc });
                    }
                }
            }
            steps++;
        }
        return -1;
    }
}

The Python solution uses BFS to explore paths in the forest grid to reach trees by height order. It lists all trees with their respective heights and sorts them before computing the shortest path between consecutively taller trees using BFS. If a tree is unreachable, it returns -1.

Complexity

The time complexity for the BFS based solution is O(T * m * n), and space complexity is O(m * n). Here T is the number of trees.

Try this approach in the editor

Approach 2: Bidirectional BFS for Optimal Path Finding

Using Bidirectional BFS can help in optimizing the pathfinding step by searching from both the start and the goal concurrently. The aim is to decrease the search space substantially as the two searches meet in the middle. This method is an extension to the regular BFS approach, potentially optimizing the traversal cost considerably under specific configurations.

from typing import List, Tuple
from collections import deque

class Solution:
    directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
    
    def serialize(self, r: int, c: int, cols: int) -> int:
        return r * cols + c
    
    def deserialize(self, key: int, cols: int) -> Tuple[int, int]:
        return (key // cols, key % cols)
    
    def bidirectional_bfs(self, forest: List[List[int]], sr: int, sc: int, tr: int, tc: int):
        if sr == tr and sc == tc:
            return 0
        rows, cols = len(forest), len(forest[0])
        q1 = deque([self.serialize(sr, sc, cols)])
        q2 = deque([self.serialize(tr, tc, cols)])
        visited1 = {self.serialize(sr, sc, cols)}
        visited2 = {self.serialize(tr, tc, cols)}
        steps = 0
        while q1 and q2:
            if len(q1) > len(q2):
                q1, q2 = q2, q1
                visited1, visited2 = visited2, visited1
            steps += 1
            for _ in range(len(q1)):
                current = q1.popleft()
                r, c = self.deserialize(current, cols)
                for dr, dc in self.directions:
                    nr, nc = r + dr, c + dc
                    if 0 <= nr < rows and 0 <= nc < cols and forest[nr][nc] > 0:
                        nxt = self.serialize(nr, nc, cols)
                        if nxt in visited2:
                            return steps
                        if nxt not in visited1:
                            visited1.add(nxt)
                            q1.append(nxt)
        return -1

    def cutOffTree(self, forest: List[List[int]]) -> int:
        trees = [(height, r, c)
                 for r, row in enumerate(forest)
                 for c, height in enumerate(row) if height > 1]
        trees.sort()
        sr, sc = 0, 0
        total_steps = 0
        for _, tr, tc in trees:
            steps = self.bidirectional_bfs(forest, sr, sc, tr, tc)
            if steps == -1:
                return -1
            total_steps += steps
            sr, sc = tr, tc
        return total_steps
// C++ code snippet for implementing bidirectional BFS
#include<vector>
#include<queue>
#include<unordered_set>

using namespace std;

class Solution {
public:
    vector<vector<int>> directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    pair<int,int> serialize(int r, int c, int interCol) {
        return make_pair(r * interCol + c, 0);
    }

    vector<int> deserialize(int key, int interCol) {
        return {key / interCol, key % interCol};
    }

    int bidirectionalBFS(vector<vector<int>>& forest, int sr, int sc, int tr, int tc) {
        if (sr == tr && sc == tc) return 0;
        int m = forest.size(), n = forest[0].size();
        queue<pair<int, int>> q1, q2;
        unordered_set<int> visited1, visited2;
        q1.emplace(serialize(sr, sc, n));
        q2.emplace(serialize(tr, tc, n));
        visited1.insert(serialize(sr, sc, n));
        visited2.insert(serialize(tr, tc, n));
        int steps = 0;
        while (!q1.empty() && !q2.empty()) {
            // Always extend the smaller queue
            if (q1.size() > q2.size()) swap(q1, q2), swap(visited1, visited2);
            steps++;
            int sz = q1.size();
            while (sz--) {
                int key, dir;
                tie(key, dir) = q1.front(); q1.pop();
                vector<int> pos = deserialize(key, n);
                for (const vector<int> &direction : directions) {
                    int nr = pos[0] + direction[0], nc = pos[1] + direction[1];
                    int newKey = serialize(nr, nc, n);
                    if (nr >= 0 && nr < m && nc >= 0 && nc < n && forest[nr][nc] > 0) {
                        if (visited2.count(newKey)) return steps;
                        if (!visited1.count(newKey)) {
                            visited1.insert(newKey);
                            q1.emplace(newKey);
                        }
                    }
                }
            }
        }
        return -1;
    }

    int cutOffTree(vector<vector<int>>& forest) {
        vector<vector<int>> trees;
        int m = forest.size(), n = forest[0].size();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (forest[i][j] > 1) trees.push_back({forest[i][j], i, j});
            }
        }
        sort(trees.begin(), trees.end());
        int sr = 0, sc = 0, total_steps = 0;
        for (auto& tree : trees) {
            int tr = tree[1], tc = tree[2];
            int steps = bidirectionalBFS(forest, sr, sc, tr, tc);
            if (steps == -1) return -1;
            total_steps += steps;
            sr = tr;
            sc = tc;
        }
        return total_steps;
    }
};
Implementing a complete bidirectional BFS in C is complex and often involves intricate management of forward and backward search queues and visited states. This might require substantial utility function support for handling interaction between the dual BFS processes, often involving custom management of states.

Python realizes the bidirectional search using dual BFS queues for start and target, merging states reached from both ends. It prioritizes advancing the search queue with fewer elements, thereby optimizing space and efficiency. The express serialization of nodes helps manage state transitions seamlessly.

Complexity

Potential time complexity savings in bidirectional BFS occur when searching is effectively partitioned; thus collapsing normally O(T * (m*n)) times into fewer steps, and reducing BFS exploration redundancy seen in singular direction searches significantly, while maintaining square-like spatial holdings in O(m*n).

Try this approach in the editor

Approach 3: Default Approach

var dirs = [][]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}

type tree struct {
	height int
	pos    int
}

func cutOffTree(forest [][]int) int {
	row, col := len(forest), len(forest[0])

	bfs := func(start, end int) int {
		q := []int{start}
		vis := make(map[int]bool)
		vis[start] = true
		step := 0
		for n := len(q); n > 0; n = len(q) {
			for i := 0; i < n; i++ {
				state := q[0]
				q = q[1:]
				if state == end {
					return step
				}
				for k := 0; k < 4; k++ {
					x, y := state/col+dirs[k][0], state%col+dirs[k][1]
					nxt := x*col + y
					if x >= 0 && x < row && y >= 0 && y < col && forest[x][y] != 0 && !vis[nxt] {
						q = append(q, nxt)
						vis[nxt] = true
					}
				}
			}
			step++
		}
		return -1
	}

	var trees []tree
	for i := 0; i < row; i++ {
		for j := 0; j < col; j++ {
			if forest[i][j] > 1 {
				trees = append(trees, tree{forest[i][j], i*col + j})
			}
		}
	}
	sort.Slice(trees, func(i, j int) bool {
		return trees[i].height < trees[j].height
	})

	ans, start := 0, 0
	for _, t := range trees {
		end := t.pos
		step := bfs(start, end)
		if step == -1 {
			return -1
		}
		ans += step
		start = end
	}
	return ans
}
use std::collections::HashSet;
use std::collections::VecDeque;

const DIRS: [[i32; 2]; 4] = [[-1, 0], [1, 0], [0, -1], [0, 1]];

impl Solution {
    pub fn cut_off_tree(forest: Vec<Vec<i32>>) -> i32 {
        let (row, col) = (forest.len() as i32, forest[0].len() as i32);

        let bfs = |start: i32, end: i32| -> i32 {
            let mut queue = VecDeque::new();
            let mut vis = HashSet::new();
            queue.push_back(start);
            vis.insert(start);
            let mut step = 0;
            while !queue.is_empty() {
                let n = queue.len();
                for _ in 0..n {
                    let state = queue.pop_front().unwrap();
                    if state == end {
                        return step;
                    }
                    for k in 0..4 {
                        let x = state / col + DIRS[k][0];
                        let y = (state % col) + DIRS[k][1];
                        let nxt = x * col + y;
                        if x >= 0
                            && x < row
                            && y >= 0
                            && y < col
                            && forest[x as usize][y as usize] != 0
                            && !vis.contains(&nxt)
                        {
                            queue.push_back(nxt);
                            vis.insert(nxt);
                        }
                    }
                }
                step += 1;
            }
            -1
        };

        let mut trees = Vec::new();
        for i in 0..row {
            for j in 0..col {
                let height = forest[i as usize][j as usize];
                if height > 1 {
                    trees.push((height, i * col + j));
                }
            }
        }
        trees.sort();

        let (mut ans, mut start) = (0, 0);
        for t in &trees {
            let end = t.1;
            let step = bfs(start, end);
            if step == -1 {
                return -1;
            }
            ans += step;
            start = end;
        }
        ans
    }
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Breadth-First Search (BFS) for Shortest Path

The time complexity for the BFS based solution is O(T * m * n), and space complexity is O(m * n). Here T is the number of trees.

Bidirectional BFS for Optimal Path Finding

Potential time complexity savings in bidirectional BFS occur when searching is effectively partitioned; thus collapsing normally O(T * (m*n)) times into fewer steps, and reducing BFS exploration redundancy seen in singular direction searches significantly, while maintaining square-like spatial holdings in O(m*n).

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
BFS Shortest Path Between TreesO(T * m * n)O(m * n)General solution for grid shortest paths where movement cost is uniform
Bidirectional BFSO(T * m * n)O(m * n)When start and target are far apart and you want faster practical performance

Frequently asked questions

Is Cut Off Trees for Golf Event easy or hard?

Cut Off Trees for Golf Event is classified as Hard on LeetCode. The difficulty comes from combining multiple concepts: sorting targets, repeatedly computing shortest paths in a matrix, handling unreachable cells, and optimizing BFS traversal across the grid.

Cut Off Trees for Golf Event Python/Java solution

Most implementations follow the same pattern across languages. First collect and sort all trees by height, then run BFS from the current position to each tree sequentially. Python typically uses collections.deque for BFS, while Java uses a Queue such as ArrayDeque.

How to solve Cut Off Trees for Golf Event in O(n)?

The problem cannot be solved in strict O(n) because multiple shortest-path searches are required across the grid. The optimal practical approach sorts trees and performs BFS between them, resulting in O(T * m * n) time. Bidirectional BFS can reduce explored nodes but does not change the worst-case complexity.

What is the best approach for Cut Off Trees for Golf Event?

The most reliable approach is sorting trees by height and running Breadth-First Search (BFS) between consecutive trees. BFS guarantees the shortest path in an unweighted grid. The algorithm repeatedly finds the shortest path from the current position to the next smallest tree, giving overall time complexity of O(T * m * n).

Is Cut Off Trees for Golf Event asked at Google/Amazon/Meta?

Cut Off Trees for Golf Event is considered a hard grid traversal problem that tests BFS, graph modeling, and pathfinding. Variants of shortest-path grid problems frequently appear in interviews at companies like Amazon, Google, and Meta because they evaluate graph reasoning and algorithm optimization.

What data structure is used in Cut Off Trees for Golf Event?

The main data structures are a queue for BFS traversal, a visited set or matrix to avoid revisiting cells, and a sorted list or heap (priority queue) to process trees in increasing height order. The grid itself is treated as a graph where each cell connects to its four neighbors.

What is the time complexity of Cut Off Trees for Golf Event?

The typical solution runs BFS for each tree after sorting them by height. If the grid size is m × n and there are T trees, each BFS can visit up to m*n cells. The total time complexity is O(T * m * n), with space complexity O(m * n) for the queue and visited structure.

Comments

Now write it yourselfClose this page and solve Cut Off Trees for Golf Event in the editor, without looking.
Practise Cut Off Trees for Golf Event