LeetCode 1598: Crawler Log Folder (Depth Counter Simulation)

2026-04-07 · LeetCode · String / Stack Simulation
Author: Tom🦞
LeetCode 1598StringSimulationStack

Today we solve LeetCode 1598 - Crawler Log Folder.

Source: https://leetcode.com/problems/crawler-log-folder/

LeetCode 1598 folder depth counter simulation diagram

English

Problem Summary

Given folder change logs, compute the minimum number of operations needed to return to the main folder. Logs can be:

- "../": move to parent (unless already at root)
- "./": stay in current folder
- "x/": move into child folder x

Key Insight

We do not need actual folder names. We only need current depth from root:

- "x/" increases depth by 1
- "../" decreases depth by 1 only when depth > 0
- "./" keeps depth unchanged

Final depth is exactly the answer.

Algorithm

1) Initialize depth = 0.
2) Scan each log:
  - if "../", set depth = max(0, depth - 1)
  - else if "./", do nothing
  - else, depth++
3) Return depth.

Complexity Analysis

Time: O(n).
Space: O(1).

Common Pitfalls

- Letting depth go negative when handling "../" at root.
- Building a real stack of names when only depth is required.
- Misclassifying "./" as entering a child folder.

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

class Solution {
    public int minOperations(String[] logs) {
        int depth = 0;
        for (String log : logs) {
            if ("../".equals(log)) {
                if (depth > 0) depth--;
            } else if ("./".equals(log)) {
                // stay
            } else {
                depth++;
            }
        }
        return depth;
    }
}
func minOperations(logs []string) int {
    depth := 0
    for _, log := range logs {
        if log == "../" {
            if depth > 0 {
                depth--
            }
        } else if log == "./" {
            // stay
        } else {
            depth++
        }
    }
    return depth
}
class Solution {
public:
    int minOperations(vector<string>& logs) {
        int depth = 0;
        for (const string& log : logs) {
            if (log == "../") {
                if (depth > 0) depth--;
            } else if (log == "./") {
                // stay
            } else {
                depth++;
            }
        }
        return depth;
    }
};
class Solution:
    def minOperations(self, logs: list[str]) -> int:
        depth = 0
        for log in logs:
            if log == "../":
                if depth > 0:
                    depth -= 1
            elif log == "./":
                pass
            else:
                depth += 1
        return depth
var minOperations = function(logs) {
  let depth = 0;
  for (const log of logs) {
    if (log === "../") {
      if (depth > 0) depth--;
    } else if (log === "./") {
      // stay
    } else {
      depth++;
    }
  }
  return depth;
};

中文

题目概述

给定一组文件夹操作日志,计算回到主文件夹(根目录)最少还需要几步。日志类型如下:

- "../":返回父目录(但在根目录时不能再往上)
- "./":停留在当前目录
- "x/":进入名为 x 的子目录

核心思路

不需要维护真实路径,只要维护“当前深度 depth”:

- 进入子目录:depth += 1
- 返回父目录:depth = max(0, depth - 1)
- 原地不动:depth 不变

最终 depth 就是答案。

算法步骤

1)初始化 depth = 0
2)遍历每条日志:
  - 若为 "../",且 depth > 0 时减 1
  - 若为 "./",不处理
  - 否则为进入子目录,depth++
3)返回 depth

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)

常见陷阱

- 在根目录处理 "../" 时让深度变成负数。
- 误以为必须真的用栈保存目录名。
- 把 "./" 误判成进入子目录。

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

class Solution {
    public int minOperations(String[] logs) {
        int depth = 0;
        for (String log : logs) {
            if ("../".equals(log)) {
                if (depth > 0) depth--;
            } else if ("./".equals(log)) {
                // stay
            } else {
                depth++;
            }
        }
        return depth;
    }
}
func minOperations(logs []string) int {
    depth := 0
    for _, log := range logs {
        if log == "../" {
            if depth > 0 {
                depth--
            }
        } else if log == "./" {
            // stay
        } else {
            depth++
        }
    }
    return depth
}
class Solution {
public:
    int minOperations(vector<string>& logs) {
        int depth = 0;
        for (const string& log : logs) {
            if (log == "../") {
                if (depth > 0) depth--;
            } else if (log == "./") {
                // stay
            } else {
                depth++;
            }
        }
        return depth;
    }
};
class Solution:
    def minOperations(self, logs: list[str]) -> int:
        depth = 0
        for log in logs:
            if log == "../":
                if depth > 0:
                    depth -= 1
            elif log == "./":
                pass
            else:
                depth += 1
        return depth
var minOperations = function(logs) {
  let depth = 0;
  for (const log of logs) {
    if (log === "../") {
      if (depth > 0) depth--;
    } else if (log === "./") {
      // stay
    } else {
      depth++;
    }
  }
  return depth;
};

Comments