owned this note
owned this note
Published
Linked with GitHub
---
title: 【LeetCode】0071. Simplify Path
date: 2018-12-25
is_modified: false
disqus: cynthiahackmd
categories:
- "面試刷題"
tags:
- "LeetCode"
---
{%hackmd @CynthiaChuang/Github-Page-Theme %}
<br>
Given an absolute path for a file (Unix-style), simplify it.
<!--more-->
For example,
**path** = `"/home/"`, => `"/home"`
**path** = `"/a/./b/../../c/"`, => `"/c"`
**path** = `"/a/../../b/../c//.//"`, => `"/c"`
**path** = `"/a//b////c/d//././/.."`, => `"/a/b/c"`
In a UNIX-style file system, a period ('.') refers to the current directory, so it can be ignored in a simplified path.
Additionally, a double period ("..") moves up a directory, so it cancels out whatever the last directory was. For more information, look here: [https://en.wikipedia.org/wiki/Path_(computing)#Unix_style](https://en.wikipedia.org/wiki/Path_(computing)#Unix_style)
<br>
**Corner Cases:**
- Did you consider the case where **path**= `"/../"`?
In this case, you should return `"/"`.
- Another corner case is the path might contain multiple slashes `'/'` together, such as `"/home//foo/"`.
In this case, you should ignore redundant slashes and return `"/home/foo"`.
<br>
**Related Topics:** `String`、`Stack`
## 解題邏輯與實作
這題是要將給定的路徑進行簡化,路徑中可能會出現的元素有三種分別是 `.` 、 `..` 及 folder 或 file(先假裝他們是吧,不然我也不知道怎麼稱呼他們XD)
如果熟悉 Unix 的路徑規則的話,應該會認的這幾個符號,我用自己的想法稍微做個歸納,不過路徑規則不熟的話好像也沒關係,花點時間找一下題目規律而已:
1. `.`
表示,同一層目錄,可以直接跳過不參考
2. `..`
表示返回上一層,所以應該取消(刪除)上一個的路徑指令,另外根據 Corner Cases 給的提示,若上一層超過所給定的路徑,直接回傳 '/'
另外需要處理的就是正規化左斜線,去除冗餘的斜線。
## Stack
這題可以使用 stack 來實做,依照上面的解題邏輯:遇到 `.` 就跳過、 `..` 就 pop,若非以上兩者就 push 進 stack,整題實做流程如下:
1. 使用 Regular Expression ,先將路徑正規化
2. 將路徑依左斜線切斷後,依序取出
1. 若為 `.` ,就跳過不執行
2. 若為 `..` 就,且 stack 不為空,就 pop 最頂層元素
3. 若非以上兩者,就當作是一個 folder 或 file,將它 push 進入 stack
3. 最後將 stack 中的結果使用左斜線串接起來
```python=
import re
class Solution:
def preprocess(self,path):
reg = r'/+'
path = re.sub(reg, "/", path)
path = path.strip('/')
return path.split("/")
def simplifyPath(self, path):
stack = []
tokens = self.preprocess(path)
for t in tokens:
if t == '.':
continue
elif t == '..':
if len(stack) > 0:
stack.pop()
else :
stack.append(t)
return "/"+"/".join(stack)
```
不過跑出來的效能有點不盡理想,只有 96 ms, 2.95% 。
<br>
所以稍微 Tune 了一下,放棄使用 Regular Expression 做正規化了,改成直接使用左斜線切斷後,若是遇到需要正規化的部份,切斷後的結果會是空字串,此時跳過不處理,就可以達到對左斜線做正規化的效果了。
```python=
class Solution:
def simplifyPath(self, path):
stack = []
tokens = path.split("/")
for t in tokens:
if len(t) == 0 or t == '.':
continue
elif t == '..':
stack = stack[:-1]
else :
stack.append(t)
return "/"+"/".join(stack)
```
跑出來的效能果然進步許多,52 ms, 49.56% ,雖然還是沒有過半…
## 其他連結
1. [【LeetCode】0000. 解題目錄](/x62skqpKStKMxRepJ6iqQQ)
<br><br>
> **本文作者**: 辛西亞.Cynthia
> **本文連結**: [辛西亞的技能樹](https://cynthiachuang.github.io/LeetCode-0071-Simplify-Path) / [hackmd 版本](https://hackmd.io/@CynthiaChuang/LeetCode-0071-Simplify-Path)
> **版權聲明**: 部落格中所有文章,均採用 [姓名標示-非商業性-相同方式分享 4.0 國際](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en) (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!