71. Simplify Path**

本文介绍了一种算法,用于简化Unix风格文件系统的绝对路径,通过解析和处理路径字符串,将其转换为最短的规范路径。文章提供了详细的代码示例,包括使用栈和字符串流的两种实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

71. Simplify Path**

https://leetcode.com/problems/simplify-path/

题目描述

Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path.

In a UNIX-style file system, a period . refers to the current directory. Furthermore, a double period .. moves the directory up a level. For more information, see: Absolute path vs relative path in Linux/Unix

Note that the returned canonical path must always begin with a slash /, and there must be only a single slash / between two directory names. The last directory name (if it exists) must not end with a trailing /. Also, the canonical path must be the shortest string representing the absolute path.

Example 1:

Input: "/home/"
Output: "/home"
Explanation: Note that there is no trailing slash after the last directory name.

Example 2:

Input: "/../"
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: "/home//foo/"
Output: "/home/foo"
Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one.

Example 4:

Input: "/a/./b/../../c/"
Output: "/c"

Example 5:

Input: "/a/../../b/../c//.//"
Output: "/c"

Example 6:

Input: "/a//b////c/d//././/.."
Output: "/a/b/c"

C++ 实现 1

在编写代码之前, 可以多检查一些例子:

path = "/home/../", => "/"
path = "/a/./b/../c/", => "/a/c"
path = "/a/./b/c/", => "/a/b/c"

首先, 处理路径我们可以考虑用栈. 我考虑用栈来保存真实的目录, 比如 home, a, b, c 之类的, 而不保存空字符, 或者 . 以及 .., 另外也不保存 /.

如果遇到 .., 那么检查栈是否不为空, 如果不为空, 将最近的目录给弹出来; 否则不做任何处理;
如果遇到 ., 那么也不做任何处理;
如果遇到既不是 . 也不是 .. 的真实目录, 则将该目录入栈;
另外对于 // 的处理就是略过.

使用 ij 来检查 path[i, j) 是否为真实的目录. 另外, 栈不一定要用 stack 来实现, vector 也行.

class Solution {
public:
    string simplifyPath(string path) {
        vector<string> st;
        int i = 1;
        while (i < path.size()) {
            int j = i;
            while (j < path.size() && path[j] != '/') ++ j;
            if (j == i) ++ i; // 遇到了 `//` 的情况
            else {
                auto dir = path.substr(i, j - i);
                if (dir == ".." && st.size() > 0) st.pop_back();
                else if (dir != ".." && dir != ".") st.push_back(dir);
                i = ++ j;
            }
        }
        string res = "/";
        for (auto &dir : st)
            res += dir + "/";
        return res.size() > 1 ? res.substr(0, res.size() - 1) : res;
    }
};

C++ 实现 2

两年前的代码. C++ 中可以使用 stringstream 来处理字符串, 而 getline 函数的最后一个参数可以设置 delimiter. 代码如下:

class Solution {
public:
    string simplifyPath(string path) {
        vector<string> stk;
        stringstream ss(path);
        string res;
        string tmp;
        // 如果 tmp 为空或者为 ., 那么直接略过
        // 如果 tmp 为 .., 那么将上一层挨着的路径给略过
        // 将所有不为 .. 的字符存入到 stk 中
        while (getline(ss, tmp, '/')) {
            if (tmp == "" || tmp == ".") continue;
            if (tmp == ".." && !stk.empty()) stk.pop_back();
            else if (tmp != "..") stk.push_back(tmp);
        }
        for (auto &str : stk) res += "/" + str;
        return res.empty() ? "/" : res;
    }
};
bool jpg_to_lcd (int * lcd_mp,char * filename,int start_x,int start_y) { //参数有效性分析,判断LCD内存映射的地址是否有效 if(NULL == lcd_mp) { printf("lcd mp is invaild\n"); return false; } /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ struct jpeg_decompress_struct cinfo; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct jpeg_error_mgr jerr; /* More stuff */ FILE * infile; /* source file */ unsigned char * buffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ /* In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ if ((infile = fopen(filename, "rb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); return false; } /* Step 1: allocate and initialize JPEG decompression object */ /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error(&jerr); /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src(&cinfo, infile); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header(&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.txt for more info. */ //判断图片是否超出分辨率 if(cinfo.output_width > 800 || cinfo.output_height > 480) { printf("[%s] width or height is too long\n", filename); return false; } /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ (void) jpeg_start_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; //计算一行的大小 /* Make a one-row-high sample array that will go away when done with image */ buffer = calloc(1,row_stride); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ int data = 0; while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ (void) jpeg_read_scanlines(&cinfo, &buffer, 1); //从上到下,从左到右 RGB RGB RGB RGB for (int i = 0; i < cinfo.output_width; ++i) //012 345 { data |= buffer[3*i]<<16; //R data |= buffer[3*i+1]<<8; //G data |= buffer[3*i+2]; //B //把像素点写入到LCD的指定位置 lcd_mp[800*start_y + start_x + 800*(cinfo.output_scanline-1) + i] = data; data = 0; } } /* Step 7: Finish decompression */ (void) jpeg_finish_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ fclose(infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). */ /* And we're done! */ return true; } 这段代码每句话的意思
最新发布
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值