71简化路径(栈、暴力模拟)

1、题目描述

以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。

在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix中的绝对路径 vs 相对路径

请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。

2、示例

输入:"/a//bc/d//././/.."
输出:"/a/b/c"

3、题解

解法一:

基本思想:栈,因为C++中string没有split成员函数,所以导致这道题有点复杂。循环遍历path每个字符,遇到/../栈弹出一个元素,遇到/.../入栈,遇到/./直接跳过,遇到/.a/入栈,其他情况/a/入栈。

解法二:

基本思想:暴力模拟,先去除多余/和/./并且将/...a/中连续大于两个.的替换成*,因为此时.算是路径名了。然后从末尾往前遍历path,对/../处理,cnt计数.数,cnt数表示需要删除/的数量,这样/../就删除此级以及上一级。最后如果path中存在*替换回.

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
	string simplifyPath(string path) {
		//基本思想:栈,因为C++中string没有split成员函数,所以导致这道题有点复杂
		//循环遍历path每个字符,遇到/../栈弹出一个元素,遇到/.../入栈,遇到/./直接跳过,遇到/.a/入栈,其他情况/a/入栈
		vector<string> vec;
		string res;
		int i, flag, pos;
		if (path.size() == 0)
			return path;
		if (path[path.size() - 1] != '/')
			path.append("/");
		i = 0;
		while (i < path.size() - 1)
		{
			pos = i;
			if (path[i] == '.')
			{
				//遇到/../栈弹出一个元素;遇到/.../入栈
				if (path[i + 1] == '.')
				{
					i = i + 2;
					flag = 0;
					while (path[i] != '/')
					{
						flag = 1;
						i++;
					}
					//遇到/.../入栈
					if (flag == 1)
					{
						vec.push_back(path.substr(pos, i - pos));
					}
					//遇到/../栈弹出一个元素
					else
					{
						if (!vec.empty())
							vec.pop_back();	
					}
					continue;
				}
				//遇到/./直接跳过
				else if (path[i + 1] == '/')
				{
					i++;
					continue;
				}
				//遇到/.a/入栈
				else
				{
					while (path[i] != '/')
						i++;
					vec.push_back(path.substr(pos, i - pos));
				}
			}
			//其他情况/a/入栈
			else if(path[i]!='/')
			{
				while (path[i] != '/')
					i++;
				vec.push_back(path.substr(pos, i - pos));
			}
			i++;
		}
		//将栈中所有元素拼接到res返回最终结果
		res = "/";
		for (i = 0; i < vec.size(); i++)
		{
			res += vec[i];
			res += "/";
		}
		if (res != "/")
			res.erase(res.size() - 1, 1);
		return res;
	}
};
class Solution1 {
public:
	string simplifyPath(string path) {
		//基本思想:暴力模拟,先去除多余/和/./并且将/...a/中连续大于两个.的替换成*,因为此时.算是路径名了
		//然后从末尾往前遍历path,对/../处理,cnt计数.数,cnt数表示需要删除/的数量,这样/../就删除此级以及上一级
		string res;
		int i, j, cnt, pos, flag = 0;
		if (path.size() == 0)
			return path;
		if (path[path.size() - 1] != '/')
			path.append("/");
		i = 0;
		while (i < path.size() - 1)
		{
			//删除多余/
			while (path[i] == '/' && path[i + 1] == '/')
			{
				path.erase(i, 1);
			}
			if (path[i] == '.')
			{
				//对/../和/.../情况处理,对/.../情况点替换成*
				if (path[i + 1] == '.')
				{
					pos = i;
					i = i + 2;
					flag = 0;
					while (path[i] != '/')
					{
						flag = 1;
						i++;
					}
					if (flag == 1)
					{
						for (j = pos; j < i; j++)
						{
							if (path[j] == '.')
								path[j] = '*';
						}
					}
					continue;
				}
				//对/./情况处理,删除
				else if (path[i + 1] == '/')
				{
					path.erase(i, 2);
					while (i < path.size() && path[i] == '/')
					{
						path.erase(i, 1);
					}
					continue;
				}
				//对/.hiden/情况处理,点替换成*
				else
				{
					path[i] = '*';
				}
			}	
			++i;
		}
		i = path.size() - 1;
		//从末尾往前遍历path,对/../处理,cnt计数.数,cnt数表示需要删除/的数量,这样/../就删除此级以及上一级
		while (i >= 0)
		{
			if (path[i] == '.')
			{
				cnt = 1;
				pos = i;
				i--;
				while (i >= 0 && cnt > 0)
				{
					if (path[i] == '.')
						cnt++;
					if (path[i] == '/')
						cnt--;
					i--;
				}
				//从下标i+1开始删除pos-i个元素
				if (cnt == 0)
					path.erase(i + 1, pos - i);
				//i已经到0了,所以从下标0开始删除pos-i个元素
				else
					path.erase(0, pos - i);
				continue;
			}
			i--;
		}
		//删除path最后面的/
		if(path!="/")
		    path.erase(path.size() - 1, 1);
		//如果path中存在*替换回.
		for (auto& v : path)
		{
			if (v == '*')
				v = '.';
		}
		return path;
	}
};
int main()
{
	Solution solute;
	string path = "/a//bc/d//././/..";
	cout << solute.simplifyPath(path) << endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值