Technical Analysis & Algorithm Visualization
The Unix Path Simplifier transforms absolute Unix-style paths into their canonical form by processing path components and applying Unix filesystem navigation rules.
Validate absolute path format and constraints
Split path by '/' separator into components
Process each component using stack operations
Build canonical path from stack contents
/**
* @param {string} path
* @return {string}
*/
var simplifyPath = function (path) {
// 1. 入力検証(LeetCode環境では制約保証済み)
if (!path || path[0] !== "/") return "/";
// 2. パス構成要素分割(連続スラッシュも自動処理)
const components = path.split("/");
// 3. スタック初期化(事前サイズ確保でV8最適化)
const stack = [];
stack.length = 0; // V8: 配列長明示でメモリ最適化
// 4. 各構成要素処理(効率的ループ)
for (let i = 0; i < components.length; i++) {
const component = components[i];
// 空文字列・現在ディレクトリ指定をスキップ
if (component === "" || component === ".") {
continue;
}
// 親ディレクトリ指定処理
if (component === "..") {
// ルート以外で親に移動
if (stack.length > 0) {
stack.pop(); // V8最適化: length更新自動
}
} else {
// 有効なディレクトリ/ファイル名追加
stack.push(component);
}
}
// 5. 正規化パス構築
// ルートディレクトリ特別処理
if (stack.length === 0) {
return "/";
}
// パス結合(効率的文字列生成)
return "/" + stack.join("/");
};
/**
* 入力検証ヘルパー(開発環境用)
* @param {string} path - Unix絶対パス
* @throws {TypeError} - 不正な型
* @throws {RangeError} - 制約違反
*/
function validateInput(path) {
if (typeof path !== "string") {
throw new TypeError("Path must be a string");
}
if (path.length === 0 || path.length > 3000) {
throw new RangeError("Path length must be 1-3000 characters");
}
if (path[0] !== "/") {
throw new Error("Path must be absolute (start with /)");
}
}
Skip empty strings from consecutive slashes and current directory markers
Pop from stack if not at root, otherwise ignore
Push valid directory/file names (including '...', '....', etc.) to stack
// 型定義セクション
type UnixPath = string & { readonly __brand: unique symbol };
type PathComponent = string;
type PathStack = PathComponent[];
// パス構成要素の型定義(Union Types活用)
type SpecialComponent = "." | ".." | "";
type ValidComponent = Exclude;
// アルゴリズムオプション
interface PathSimplifyOptions {
readonly strictValidation?: boolean;
readonly preserveTrailingSlash?: boolean;
}
// メイン関数(LeetCode形式)
function simplifyPath(path: string): string {
// 1. 入力型検証(型ガード)
if (!isValidUnixPath(path)) {
return "/";
}
// 2. パス構成要素分割(型安全な操作)
const components: PathComponent[] = path.split("/");
// 3. 型安全なスタック初期化
const stack: PathStack = [];
// 4. 構成要素処理(型ガード活用)
for (const component of components) {
processPathComponent(component, stack);
}
// 5. 正規化パス構築(型安全)
return buildCanonicalPath(stack);
}
/**
* Unix絶対パス判定(型ガード)
*/
function isValidUnixPath(path: string): path is UnixPath {
return (
typeof path === "string" &&
path.length > 0 &&
path.length <= 3000 &&
path[0] === "/"
);
}
/**
* パス構成要素処理(型安全 + インライン最適化)
*/
function processPathComponent(
component: PathComponent,
stack: PathStack
): void {
// 型ガードによる効率的分岐
if (isEmptyOrCurrent(component)) {
return; // 早期リターンでV8最適化
}
if (isParentDirectory(component)) {
handleParentDirectory(stack);
return;
}
// 有効なディレクトリ/ファイル名
if (isValidComponent(component)) {
stack.push(component);
}
}
/**
* 空文字列・現在ディレクトリ判定(型ガード + インライン化)
*/
function isEmptyOrCurrent(component: PathComponent): component is "" | "." {
return component === "" || component === ".";
}
/**
* 親ディレクトリ判定(型ガード)
*/
function isParentDirectory(component: PathComponent): component is ".." {
return component === "..";
}
/**
* 有効な構成要素判定(型ガード)
*/
function isValidComponent(
component: PathComponent
): component is ValidComponent {
return component !== "" && component !== "." && component !== "..";
}
/**
* 親ディレクトリ処理(型安全なスタック操作)
*/
function handleParentDirectory(stack: PathStack): void {
if (stack.length > 0) {
stack.pop(); // V8最適化: 型情報でlength更新最適化
}
}
/**
* 正規化パス構築(型安全な文字列操作)
*/
function buildCanonicalPath(stack: ReadonlyArray): string {
// ルートディレクトリ特別処理(const assertion活用)
if (stack.length === 0) {
return "/" as const;
}
// 効率的パス結合(Template Literal活用可能性)
return `/${stack.join("/")}`;
}
/**
* 型安全な入力検証(開発環境用)
*/
function validateInput(path: unknown): asserts path is string {
if (typeof path !== "string") {
throw new TypeError(`Expected string, got ${typeof path}`);
}
if (path.length === 0 || path.length > 3000) {
throw new RangeError(`Path length must be 1-3000, got ${path.length}`);
}
if (!path.startsWith("/")) {
throw new Error("Path must be absolute (start with /)");
}
}
/**
* 高機能版実装(業務開発用、LeetCode提出時は削除)
*/
function simplifyPathAdvanced(
path: string,
options: PathSimplifyOptions = {}
): string {
const { strictValidation = false } = options;
if (strictValidation) {
validateInput(path);
}
return simplifyPath(path);
}
from collections import deque
from typing import Any, List, Optional
# import sys
class Solution:
"""
Unix Path Simplifier
競技プログラミング向けと業務開発向けの2パターンを提供
"""
def simplifyPath(self, path: str) -> str:
"""
LeetCode提出用メソッド(競技プログラミング最適化)
Args:
path: Unix絶対パス文字列
Returns:
正規化された絶対パス
Time Complexity: O(n)
Space Complexity: O(n)
"""
# CPython最適化:dequeによる高速スタック操作
stack: deque[str] = deque()
# 組み込み関数split()活用(C実装で高速)
components = path.split("/")
# リスト走査(CPythonで最適化済み)
for component in components:
# 早期継続でブランチ予測最適化
if component in ("", "."):
continue
elif component == "..":
# deque.pop()はO(1)(listより高速)
if stack:
stack.pop()
else:
# 有効なディレクトリ/ファイル名
stack.append(component)
# 効率的文字列結合(join()のC実装活用)
return "/" + "/".join(stack) if stack else "/"
def simplify_path_production(
self, path: str, *, strict_validation: bool = True
) -> str:
"""
業務開発向け実装(型安全・エラーハンドリング重視)
Args:
path: Unix絶対パス文字列
strict_validation: 厳密な入力検証を行うかどうか
Returns:
正規化された絶対パス
Raises:
ValueError: パス形式が不正な場合
TypeError: 引数型が不正な場合
Time Complexity: O(n)
Space Complexity: O(n)
"""
# 1. 型・制約検証
if strict_validation:
self._validate_input(path)
# 2. エッジケース処理
if self._is_root_only(path):
return "/"
# 3. メインアルゴリズム(型安全)
return self._normalize_path(path)
def _validate_input(self, path: Any) -> None:
"""
型安全な入力検証
Args:
path: 検証対象のパス
Raises:
TypeError: 型が不正な場合
ValueError: 制約違反の場合
"""
if not isinstance(path, str):
raise TypeError(f"Path must be a string, got {type(path).__name__}")
if not path:
raise ValueError("Path cannot be empty")
if len(path) > 3000:
raise ValueError(f"Path length exceeds limit: {len(path)} > 3000")
if not path.startswith("/"):
raise ValueError("Path must be absolute (start with '/')")
# 不正文字チェック
invalid_chars = set(path) - set(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./_"
)
if invalid_chars:
raise ValueError(f"Invalid characters in path: {invalid_chars}")
def _is_root_only(self, path: str) -> bool:
"""
ルートディレクトリのみかどうか判定
Args:
path: 判定対象パス
Returns:
ルートのみの場合True
"""
# 効率的な文字列チェック
return path.strip("/") == ""
def _normalize_path(self, path: str) -> str:
"""
パス正規化のコアロジック
Args:
path: 正規化対象パス
Returns:
正規化されたパス
"""
# 型ヒント付きスタック初期化
stack: deque[str] = deque()
# パス構成要素分割(組み込み関数活用)
components: List[str] = [c for c in path.split("/") if c]
# 構成要素処理(型安全なイテレーション)
for component in components:
if component == ".":
continue # 現在ディレクトリは無視
elif component == "..":
# 親ディレクトリ処理(境界チェック)
if stack:
stack.pop()
else:
# 有効なディレクトリ/ファイル名追加
stack.append(component)
# 結果構築(型安全な文字列操作)
if not stack:
return "/"
return "/" + "/".join(stack)
# 型安全なヘルパー関数(業務開発用)
def validate_unix_path(path: str) -> bool:
"""
Unix絶対パスの妥当性検証
Args:
path: 検証対象パス
Returns:
妥当な場合True
"""
try:
Solution()._validate_input(path)
return True
except (TypeError, ValueError):
return False
def normalize_path_safe(path: str) -> Optional[str]:
"""
例外安全なパス正規化
Args:
path: 正規化対象パス
Returns:
正規化されたパス、失敗時はNone
"""
try:
solution = Solution()
return solution.simplify_path_production(path)
except (TypeError, ValueError):
return None
Path with no special components (., ..) - direct processing
Mixed path with some navigation components
Path with maximum parent directory references - still linear