Medium草稿★★★★★O(n) 時間 · O(n) 空間
StackString
Patterns🥞 堆疊
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

71Simplify PathStackMediumStack

給定 Unix 風格的絕對路徑字串 path,將其簡化為標準路徑 (canonical path)。規則:

  • "." 表示當前目錄
  • ".." 表示上一層目錄
  • 多個連續斜線視為單一斜線
  • 結果以 / 開頭且末尾不含 /

Example:

Input: path = “/home//foo/../bar” Output: “/home/bar”

Intuition

TIP

核心思路:用斜線分割路徑,堆疊處理目錄名稱——普通名稱 push,".." 則 pop,"." 和空字串跳過。

Approaches

1. Manual Scan (no split) — O(n) / O(n)
  • Idea: 自己掃字元切出每段,省去 split 產生的中間清單;遇 . 略過、.. 退一層、其餘入堆
  • Time: O(n)
  • Space: O(n) - 堆疊
class Solution {
    fun simplifyPath(path: String): String {
        val stack = ArrayDeque<String>()
        var i = 0
        val n = path.length
        while (i < n) {
            while (i < n && path[i] == '/') i++        // 跳過連續斜線
            val start = i
            while (i < n && path[i] != '/') i++         // 取一段
            if (i > start) {
                when (val part = path.substring(start, i)) {
                    "." -> {}
                    ".." -> if (stack.isNotEmpty()) stack.removeLast()
                    else -> stack.addLast(part)
                }
            }
        }
        return "/" + stack.joinToString("/")
    }
}
⭐ 2. Stack + Split — O(n) / O(n)
  • Idea: 用 / 分割路徑,遍歷每個部分,根據規則操作堆疊,最後以 / 連接堆疊內容
  • Time: O(n) - n 為路徑長度
  • Space: O(n)
class Solution {
    fun simplifyPath(path: String): String {
        val stack = ArrayDeque<String>()

        for (part in path.split("/")) {
            when (part) {
                "", "." -> continue
                ".." -> {
                    if (stack.isNotEmpty()) stack.removeLast()
                }
                else -> stack.addLast(part)
            }
        }

        return "/" + stack.joinToString("/")
    }
}

🔑 Takeaways