0071.简化路径 Simplify Path

问题描述

简化路径问题有几个点:

  • // 形式, 忽略掉中间的空白
  • /./ 形式, 指向当前目录, 也应该忽略
  • /../ 形式, 跳转到父目录, 应忽略当前目录, 直接转向父目录
  • 其它形式的, 应当保留

可以用 / 字符为分隔符, 把路径分隔成多个部分; 并用栈来存储每一级的目录名. 然后基于上面的规则, 移除不需要的目录名, 最后将栈中所有的字段组装成一个新的路径.

代码实现

Rust

#![allow(unused)]
fn main() {
// Stack
// 优化字符串操作
pub fn simplify_path2(path: String) -> String {
    let mut stack: Vec<&str> = Vec::with_capacity(path.len());
    for part in path.split('/') {
        match part {
            // 忽略空白
            "" => (),
            // 忽略当前目录
            "." => (),
            // 返回上个目录
            ".." => {
                let _ = stack.pop();
            }
            part => stack.push(part),
        }
    }
    // 目录以 "/" 开头
    format!("/{}", stack.join("/"))
}
}

C++

#include <cassert>

#include <sstream>
#include <string>
#include <vector>

std::string simplify_path(std::string path) {
  // 创建栈, 用于存放每个目录名.
  std::vector<std::string> stack;
  std::stringstream ss(path);
  std::string folder_name;
  while (std::getline(ss, folder_name, '/')) {
    if (folder_name.empty()) {
      // 忽略空白
    } else if (folder_name == ".") {
      // 忽略当前目录
    } else if (folder_name == "..") {
      // 返回上个目录
      if (!stack.empty()) {
        stack.pop_back();
      }
    } else {
      stack.emplace_back(folder_name);
    }
  }

  std::string real_path;
  if (stack.empty()) {
    // 目录以 "/" 开头
    real_path += "/";
  } else {
    for (const auto& folder_name : stack) {
      real_path = real_path + "/" + folder_name;
    }
  }

  return real_path;
}