【leetcode_71】【中等】simplify-path / 简化路径

URL

链接:https://leetcode-cn.com/problems/simplify-path/


题目

在这里插入图片描述
在这里插入图片描述


分析

在这里插入图片描述
在这里插入图片描述


源码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* split string */
char ** split(const char *s , char delim , int * return_size){
    int n = strlen(s);
    /* 0. 申请空间,存储分割后的字符列表 */
    char ** ans =  (char **)malloc(sizeof(sizeof(char *))*n);
    int pos = 0;
    int curr = 0;
    int len = 0;

    /* 1. 遍历path,存储/xxxxx/之间的‘路径名’ */
    while(pos < n){
        /* 重复delim时,遍历并指到最后一个delim字符 */
        while(pos < n && s[pos] == delim){
            ++pos;
        }
        /* 从delim开始,遍历到下一个delim,并指向下一个delim位置 */
        curr = pos ;
        while(pos < n && s[pos] != delim){
            ++pos;
        }
        /* 申请空间存储(delim,delim)中的‘路径名’ */
        if(curr < n){
            ans[len] = (char *)malloc(sizeof(char)*(pos - curr + 1)); //pos->delim , curr->delim , pos-curr == str_len , +1 for endl
            strncpy(ans[len] , s + curr , pos - curr);
            ans[len][pos - curr] = '\0'; // 注意结束符
            ++len; //‘路径名’ 元素个数
        }
    }
    * return_size = len ;
    return ans;
}

char * simplifyPath(char * path){
    int names_size = 0;
    int n = strlen(path);
    /* 1. 按‘/’分割原始文件路径,并存储其中的每个‘路径名’ */
    char ** names = split(path,'/',&names_size);

    /* 2. 申请 stack  */
    char ** stack = (char **)malloc(sizeof(char *) * names_size);
    int stack_size = 0;

    /* 3. 判断分割后元素是否为.. 或者. ,判断最终文件路径 */
    for(int i = 0;i < names_size ; ++i){
        if(!strcmp(names[i],"..")){//当前路径为..,则实际有效文件夹个数-1
            if(stack_size > 0){
                --stack_size;
            }
        }else if (strcmp(names[i] , ".")){//当前路径不为.,则移动分割中的元素到stack中,追加到文件stack的路径中
            stack[stack_size] = names[i];
            ++stack_size;
        }
    }

    /* 4. 申请最终存储路径的空间 */
    char * ans = (char *)malloc(sizeof(char) * (n+1));
    int curr = 0 ;
    /* 4.1 已经跳转到根目录 */
    if (stack_size == 0){
        ans[curr] = '/';
        ++curr;
    }else{
        /* 4.2 为stack中每个元素间添加'/' */
        for (int i = 0; i < stack_size; ++i){
            ans[curr] = '/';
            ++curr;
            strcpy(ans + curr, stack[i]); //start_offset of ans
            curr += strlen(stack[i]);// total_length of stack[xx]
        }
    }

    /* 4.3 addin endl */
    ans[curr] = '\0';
    /* 5.释放二级指针空间 */
    for(int i = 0;i<names_size; ++i){
        free(names[i]);
    }
    /* free mem */
    free(names);
    free(stack);
    return ans;
}

int main()
{
    char p1[] = "/home/";
    char p2[] = "/../";
    char p3[] = "/home//foo/";
    char p4[] = "/a/./b/../../c/";

    printf("before : %s\n",p1);
    printf("after  : %s\n\n",simplifyPath(p1));

    printf("before : %s\n",p2);
    printf("after  : %s\n\n",simplifyPath(p2));

    printf("before : %s\n",p3);
    printf("after  : %s\n\n",simplifyPath(p3));

    printf("before : %s\n",p4);
    printf("after  : %s\n\n",simplifyPath(p4));

    return 0;
}
before : /home/
after  : /home

before : /../
after  : /

before : /home//foo/
after  : /home/foo

before : /a/./b/../../c/
after  : /c


源码概述

  1. 以‘/’为分隔符,切分原始path,并将每个元素存储到names[]字符串列表中,并记录总“文件夹”个数。
  2. 遍历上述列表,if为…,则总文件夹个数-1,else if为.,则将当前列表中的元素赋值给最终存储的空间中ans[]。
  3. 为ans的每个元素中间添加一个’/’
  4. done.

将原始路径按“/”划分并存储在列表中,
申请stack空间存储最终有效的文件夹名称,通过判断上述列表中每个元素的操作逻辑,如… 或者 不为. --因为情况是限定的,只能是“.”、“…”、“文件名”三种情况。–来判断当前空间的元素赋值情况,为…表示当前上一元素值无效,做自减操作,后续赋值会覆盖当前位置;不为.则表示当前列表中的元素为文件夹,存储到申请的stack元素中。
申请新空间ans,存储完整且合法的路径。为每个stack元素之间添加“/”字符,使其表达方式合法。


小结

PS:
利用入栈出栈的机制,在遍历时确保当前元素始终为最终的操作目录,最后再合法化字符串即可。
三次申请内存空间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

过得精彩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值