71. Simplify Path
Problem
Tags: String
, Stack
Given a string path
, which is an absolute path (starting with a slash '/'
) to a file or directory in a Unix-style file system, convert it to the simplified canonical path.
In a Unix-style file system, a period '.'
refers to the current directory, a double period '..'
refers to the directory up a level, and any multiple consecutive slashes (i.e. '//'
) are treated as a single slash '/'
. For this problem, any other format of periods such as '...'
are treated as file/directory names.
The canonical path should have the following format:
- The path starts with a single slash
'/'
. - Any two directories are separated by a single slash
'/'
. - The path does not end with a trailing
'/'
. - The path only contains the directories on the path from the root directory to the target file or directory (i.e., no period
'.'
or double period'..'
)
Return the simplified canonical path.
Example 1:
Input: path = "/home/"
Output: "/home"
Explanation: Note that there is no trailing slash after the last directory name.
Example 2:
Input: path = "/../"
Output: "/"
Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go.
Example 3:
Input: path = "/home//foo/"
Output: "/home/foo"
Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one.
Constraints:
1 <= path.length <= 3000
path
consists of English letters, digits, period'.'
, slash'/'
or'_'
.path
is a valid absolute Unix path.
Solution
Solution
I use stack to store the path slices, but I think deque will be a better choice because we need to construct the output canonical path in the same order with the given absolute one.
The rules are simple:
".."
: pop last one."."
and""
: do nothing.- otherwise, push it.
Then we construct the canonical path by directly access the stack data (not a good way, but works because the underlying structure of my stack).
Code
C
// 71. Simplify Path (10/5/54168)
// Runtime: 0 ms (94.52%) Memory: 6.97 MB (20.55%)
#define StructStack(_name, _type) \
typedef struct _name { \
_type* data; \
uint64_t size; \
uint64_t max; \
void (*push)(struct _name*, _type); \
_type (*pop)(struct _name*); \
_type (*top)(struct _name*); \
uint8_t (*empty)(struct _name*); \
void (*clear)(struct _name*); \
void (*free)(struct _name*); \
} _name; \
void push_##_name(_name* stack, _type val) { \
if (stack->size == stack->max) { \
return; \
} \
stack->data[stack->size++] = val; \
} \
_type pop_##_name(_name* stack) { \
if (stack->size == 0) { \
return 0; \
} \
return stack->data[--stack->size]; \
} \
_type top_##_name(_name* stack) { \
if (stack->size == 0) { \
return 0; \
} \
return stack->data[stack->size - 1]; \
} \
uint8_t empty_##_name(_name* stack) { \
return stack->size == 0; \
} \
void clear_##_name(_name* stack) { \
stack->size = 0; \
} \
void free_##_name(_name* stack) { \
free(stack->data); \
free(stack); \
} \
_name* create_##_name(uint64_t max_size) { \
_name* stack = malloc(sizeof(_name)); \
stack->data = calloc(max_size, sizeof(_type)); \
stack->size = 0; \
stack->max = max_size; \
stack->push = &push_##_name; \
stack->pop = &pop_##_name; \
stack->top = &top_##_name; \
stack->empty = &empty_##_name; \
stack->clear = &clear_##_name; \
stack->free = &free_##_name; \
return stack; \
}
StructStack(Stack, char*);
char* simplifyPath(char* path) {
char* absolute = malloc(strlen(path) + 1);
strcpy(absolute, path);
Stack* stk = create_Stack(strlen(path) / 2);
char* token = strtok(absolute, "/");
while (token) {
if (strcmp(token, "..") == 0) {
stk->pop(stk);
}
else if (strlen(token) && strcmp(token, ".") != 0) {
stk->push(stk, token);
}
token = strtok(NULL, "/");
}
char* canonical = calloc(strlen(path) + 1, sizeof(char));
for (int i = 0; i < stk->size; i++) {
strcat(canonical, "/");
strcat(canonical, stk->data[i]);
}
if (strlen(canonical) == 0) {
strcat(canonical, "/");
}
free(absolute);
stk->free(stk);
return canonical;
}