Delete a Filesystem Tree
Reported by candidates from Datadog's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
The Datadog OA reported in July 2026 hands you three filesystem APIs you can't touch and asks for rm -rf. List, Delete, IsDirectory. That's it. It's a tree postorder problem dressed up as systems work, and the catch is buried in the constraints: depth up to 2,000, and recursion isn't guaranteed safe. If you've got the invite and a day or two, this is the one detail to lock in. StealthCoder sits invisibly on your screen as a safety net if you blank on the iterative version during the live OA.
The problem
DeleteTree You are given a mutable filesystem with exactly three fixed APIs: fs.List(path) returns absolute paths below path. In this exercise it returns the live direct children in arbitrary order; on a file it returns an empty list. fs.Delete(path) deletes a file or an empty directory and returns true. It returns false for a nonempty directory. fs.IsDirectory(path) returns true exactly when the live path is a directory. Every path passed to these APIs is absolute, and the APIs themselves cannot be changed. Implement DeleteTree(path), analogous to rm -rf, so that path and its entire subtree are deleted. Execution adapter The function runner represents the initial filesystem with parallel arrays paths and isDirectory. Entry isDirectory[i] describes paths[i]. The virtual root / exists but is not included in paths and is never the target. Construct the filesystem from that snapshot, perform the logical DeleteTree(targetPath) operation through the three APIs above, and return every path still present after the deletion in lexicographically increasing order. The sorted return value is only the observable judge adapter for the filesystem side effect. Required behavior Delete every descendant before attempting to delete its directory. Delete a file directly because it has no children. Do not delete any path outside the target subtree. Do not rely on the order returned by fs.List. What the interview report shared The report described the three immutable APIs, stated that all API path arguments are absolute, and asked for a recursive tree deletion with semantics similar to rm -rf. Function deleteTree(paths: List<String>, isDirectory: boolean[], targetPath: String) → List<String> Examples Example 1 paths = ["/data","/data/logs","/data/logs/2026","/data/logs/2026/app.log","/data/tmp","/data/tmp/cache.bin","/keep.txt"] isDirectory = [true,true,true,false,true,false,false] targetPath = "/data/logs" return = ["/data","/data/tmp","/data/tmp/cache.bin","/keep.txt"] /data/logs/2026/app.log is deleted first, followed by its now-empty parent directories /data/logs/2026 and /data/logs. The sibling subtree rooted at /data/tmp and /keep.txt remain. Example 2 paths = ["/a","/a/file.txt","/b","/b/keep.txt"] isDirectory = [true,false,true,false] targetPath = "/a/file.txt" return = ["/a","/b","/b/keep.txt"] The target is already a file, so it is deleted immediately. Its parent directory and the separate /b subtree remain live. Example 3 paths = ["/empty","/keep","/keep/note.txt"] isDirectory = [true,true,false] targetPath = "/empty" return = ["/keep","/keep/note.txt"] The target directory has no children, so fs.Delete succeeds on the first deletion attempt. Constraints 1 <= paths.size() <= 50,000. paths.size() == isDirectory.length. Every listed path is distinct, canonical, absolute, and different from /; no listed path has a trailing slash. The parent of each listed path is either / or another listed path marked as a directory. targetPath is one of the listed paths and is not /. The snapshot is a finite rooted tree with no symbolic links, hard links, cycles, or mount boundaries. fs.List and fs.IsDirectory do not fail, and no concurrent filesystem mutation occurs. A valid deletion fails only while the target directory is nonempty; no other partial or external failure occurs. The sum of all path lengths is at most 5,000,000, and tree depth is at most 2,000. Recursion is not guaranteed to be safe at the maximum depth.
Reported by candidates. Source: FastPrep
Pattern and pitfall
The trick is postorder deletion: every child must be gone before you delete its parent, because Delete returns false on a nonempty directory. The clean recursive version is five lines, but the problem warns that depth can hit 2,000 and recursion may not be safe. So write it iteratively with an explicit stack. Push the target. Pop a node, and if it's a file or a directory with no live children, delete it. Otherwise push it back marked as visited, then push its children from List. Or use a two-phase approach: collect nodes in preorder, then delete in reverse. Pitfalls: relying on List order, deleting outside the target subtree, and forgetting that the target itself can be a file. The return value just needs the remaining paths sorted. If the stack logic slips under pressure, StealthCoder is the hedge during the live OA.
If this hits your live OA and you blank, StealthCoder solves it in seconds, invisible to the proctor.
You can drill Delete a Filesystem Tree cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built by an Amazon engineer who would have shipped this the night before his JPMorgan OA if he'd had it.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass Datadog's OA.
Datadog reuses patterns across OAs. Built by an Amazon engineer who would have shipped this the night before his JPMorgan OA if he'd had it. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Delete a Filesystem Tree FAQ
What's the actual trick in the Datadog DeleteTree problem?+
Postorder deletion. A directory can only be deleted once it's empty, so every descendant goes first. Files delete immediately. For directories, list children, delete each subtree, then delete the directory itself. The rest is just wiring up the judge adapter.
Why does the problem warn about recursion at max depth?+
Tree depth can reach 2,000, and the statement says recursion isn't guaranteed safe. Depending on the language stack limits, a recursive solution could overflow. Use an explicit stack with a visited flag, or collect nodes in preorder and delete them in reverse order.
Do I need to build my own tree from the paths array?+
No. The adapter builds the filesystem from paths and isDirectory, and your logic only calls List, Delete, and IsDirectory. Your job is the deletion algorithm. You only sort the leftover live paths for the returned list at the end.
Can I trust the order fs.List returns?+
No. The problem says children come back in arbitrary order and you must not rely on it. That's fine for this solution, since each child subtree is independent. Just process every child before the parent and don't assume sorted output.
How do I prepare for this in 48 hours?+
Write the iterative postorder deletion once from scratch, using a stack and a visited marker. Test the three examples: a nested directory, a file target, and an empty directory target. Then practice the two-phase preorder-then-reverse variant as a backup.