leecode 解题总结:71. Simplify Path

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
/*
问题:
Given an absolute path for a file (Unix-style), simplify it.

For example,
path = "/home/", => "/home"
path = "/a/./b/../../c/", => "/c"
click to show corner cases.

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".

分析:给定unix下的绝对路径,来简化路径。
首先:"."表示当前路径, ".."表示上一层
简化条件:
1】如果路径最后一个字符是'/',删除该字符
2】出现连续多个'/',删除重复的
3】'/../',此时表示路径'/'上一层路径,实际仍然是'/',
删除的是:".."前面的A: '/'到继续向前找到A:'/'前面的B:'/'部分
如果找不到B:'/',则删除A:'/'及其前面所有字符
4】出现'.'删除其前面的一个路径
5】分析:/a/./b/../../c/,出现'.'可以直接删除,变成/a/b/../../c/
   出现'../'可以和前面的'/'部分消除,得到/a/../c/
   出现/../,删除前面一个'/'部分,得到//c/
实际处理步骤为:1先删除冗余//,2 删除'.',消除'../' , 最后消除路径最后的/(但如果只有这一个字符,就不消除)

想到另外一种解法:就是按照'/'来对字符串进行分割,分割后的每个字符串代表一个路径串

输入:
/home/
/a/./b/../../c/
/../
/home//foo/
/...
输出:
/home
/c
/
/home/foo
/...

关键:
1 简化路径关键在于将路径按照"/"进行切分,得到路径子串数组,然后利用栈对每次遇到".."就弹出路径子串来做消除

2 /...报错,应该直接返回,也就是说"..."默认不是返回路径上层的上层。
字符串截取函数
		// "/..." 会报错,只出现一次"/",也就是说如果最后结尾的不是"/"会有问题
		while(string::npos != pos)
		{
			string partialPath(path.begin() + beg , path.begin() + pos);
			if((!partialPath.empty()) && "." != partialPath )
			{
				result.push_back(partialPath);
			}
			beg = pos + 1;
			pos = path.find('/' , pos + 1);
		}
		//防止遗漏最后一个字符串
		string partialPath(path.begin() + beg , path.end());
		if((!partialPath.empty()) && "." != partialPath )
		{
			result.push_back(partialPath);
		}
*/

class Solution {
public:
	//将路径按照'/'进行切分,如果切分的字符串为空,不放入结果集
	vector mySplitStr(string path)
	{
		vector result;
		if(path.empty())
		{
			return result;
		}
		int beg = 0;
		size_t pos = path.find('/');

		//找到了,将begin~pos-1处都截取出来
		// "/..." 会报错,只出现一次"/",也就是说如果最后结尾的不是"/"会有问题
		while(string::npos != pos)
		{
			string partialPath(path.begin() + beg , path.begin() + pos);
			if((!partialPath.empty()) && "." != partialPath )
			{
				result.push_back(partialPath);
			}
			beg = pos + 1;
			pos = path.find('/' , pos + 1);
		}
		//防止遗漏最后一个字符串
		string partialPath(path.begin() + beg , path.end());
		if((!partialPath.empty()) && "." != partialPath )
		{
			result.push_back(partialPath);
		}
		return  result;
	}

	//获取栈中存放结果,需要逆置,而且需要添加"/"
	string getResult(stack& result)
	{
		stringstream stream;
		bool isFirst = true;
		vector vecResult;
		while(!result.empty())
		{
			vecResult.push_back(result.top());
			result.pop();
		}
		int size = vecResult.size();
		for(int i = size - 1 ; i >= 0 ; i--)
		{
			stream << '/' << vecResult.at(i);
		}
		return stream.str();
	}

    string simplifyPath(string path) {
        if(path.empty())
		{
			return path;
		}
		int length = path.length();
		vector paths = mySplitStr(path);
		//得到各个子串后开始处理,遇到".." 就消除当前和前面部分
		int size = paths.size();
		stack results;
		for(int i = 0 ; i < size ; i++)
		{
			if(string("..") == paths.at(i))
			{
				if(!results.empty())
				{
					results.pop();
				}
			}
			else
			{
				results.push(paths.at(i));
			}
		}
		//拼接结果
		string result = getResult(results);
		// "/../"返回"/"
		if(result.empty())
		{
			return "/";
		}
		return result;
    }
};

void print(vector& result)
{
	if(result.empty())
	{
		cout << "no result" << endl;
		return;
	}
	int size = result.size();
	for(int i = 0 ; i < size ; i++)
	{
		cout << result.at(i) << " " ;
	}
	cout << endl;
}

void process()
{
	 string value;
	 Solution solution;
	 while(cin >> value )
	 {
		 string result = solution.simplifyPath(value);
		 cout << result << endl;
	 }
}

int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}


你可能感兴趣的:(leecode)