美文网首页程序员
Leetcode刷题总结(2):字符串问题

Leetcode刷题总结(2):字符串问题

作者: 张慕晖 | 来源:发表于2018-04-04 16:50 被阅读72次

    38

    题意

    这道题的题面很有趣:生成一个这样的序列:
    1:"1"
    2:"11"(1个1)
    3:"21"(2个1)
    4:"1211"(1个2,1个1)
    5:"111221"(1个1,1个2,2个1)

    给出n,求第n个序列长什么样子。

    分析

    不妨来多计算几个数:
    6:"312211"
    7:"13112221"
    8:"1113213211"

    感觉序列长度大致是线性增长的。那就直接暴力好了。


    查看了一下题解。感觉这种东西很难有通项公式。这个序列是Conway的“Look-and-say”序列(https://en.wikipedia.org/wiki/Look-and-say_sequence),在https://leetcode.com/problems/count-and-say/discuss/16113/How-to-proof-the-COUNT-is-always-less-than-10上有更多说明,比如不会出现超过3的数字。数列长度的增长速率大约是30%。

    代码

    class Solution {
    public:
        string countAndSay(int n) {
            if (n == 1)
                return "1";
            
            vector<int> a(1, 1);
            vector<int> b;
            for (int i = 1; i < n; i++) {
                int j = 1, cnt = 1;
                while (j < a.size()) {
                    if (a[j] != a[j-1]) {
                        b.push_back(cnt);  // cnt个
                        b.push_back(a[j-1]);  // a[j-1]
                        cnt = 1;
                    }
                    else {
                        cnt++;
                    }
                    j++;
                }
                if (cnt != 0) {
                    b.push_back(cnt);
                    b.push_back(a[a.size()-1]);
                }
                a = b;
                b.clear();
            }
            
            string ans;
            for (int i = 0; i < a.size(); i++)
                ans += '0' + a[i];
            return ans;
        }
    };
    

    时间为90.54%。惊了,纯暴力这么强的么(当然也是因为推递归公式很难)。

    71

    题意

    题意倒是非常简单。给你一个Unix样式的路径,让你简化。

    分析

    最初的想法很简单。不妨假定路径是合法的,则只有3种情况:

    • 普通的路径
    • .:相当于没有
    • ..:相当于上移一层
      那就搞一个栈好了。

    在调试过程中遇到的比较不好想到的Corner case是"/.."。看起来不合法,但实际上是合法的。

    代码

    class Solution {
    public:
        string simplifyPath(string path) {
            stack<string> s;
            string dir = "";
            for (int i = 0; i < path.length(); i++) {
                if (path[i] == '/') {
                    if (dir == ".") {
                        
                    }
                    else if (dir == "..") {
                        if (!s.empty())
                            s.pop();
                    }
                    else if (dir != "") {
                        s.push(dir);
                    }
                    dir = "";
                }
                else {
                    dir += path[i];
                }
            }
            
            if (dir != "") {
                if (dir == ".") {
    
                }
                else if (dir == "..") {
                    if (!s.empty())
                        s.pop();
                }
                else if (dir != "") {
                    s.push(dir);
                }
            }
            
            if (!s.empty()) {
                dir = s.top();
                s.pop();
            }
            else {
                return "/";
            }
            
            while (!s.empty()) {
                dir = s.top() + "/" + dir;
                s.pop();
            }
            dir = "/" + dir;
            
            return dir;
        }
    };
    

    时间为31.43%,挺慢的,应该是大量使用STL导致的。

    68

    题意

    给你一个数组的单词和一个长度L,把单词排列成若干行,使得每行的宽度都恰好为L。要求每行是两端对齐的(但是最后一行是左对齐),每行贪心地容纳尽可能多的单词;单词之间的空格是平均分布的, 如果不能平均分,则左侧的空位分配更多的空格。保证每个单词的长度不超过L。

    分析

    遍历数组。可以迅速得出每行能够安排的是哪几个单词。根据单词得出空格的位置和大小即可。

    通过运行示例代码得知,如果只有一个词,是左对齐的。

    还有少量边界条件需要注意,比如判断是否能够把单词插进当前的这一行。错了几次之后很快就做出来了。

    代码

    class Solution {
    private:
        string makeSpaces(int numSpaces, int numIntv, int i) {
            int x = numSpaces / numIntv;
            if (i < numSpaces % numIntv)
                x++;
            string ans = "";
            while (x--) {
                ans += " ";
            }
            return ans;
        }
        
    public:
        vector<string> fullJustify(vector<string>& words, int maxWidth) {
            
            vector<vector<string>> lines;
            vector<string> ans;
            vector<int> sums;
            
            if (words.size() == 0 || maxWidth == 0) {
                ans.push_back("");
                return ans;
            }
            
            vector<string> line;
            int sum = 0;
            
            for (int i = 0; i < words.size(); i++) {
                // newline
                if (sum != 0 && sum + words[i].length() + 1 > maxWidth) {
                    sum -= line.size() - 1;
                    lines.push_back(line);
                    vector<string> newLine;
                    newLine.push_back(words[i]);
                    line = newLine;
                    sums.push_back(sum);
                    sum = words[i].length();
                }
                else {
                    if (sum != 0)
                        sum++;
                    sum += words[i].length();
                    line.push_back(words[i]);
                }
            }
            
            lines.push_back(line);
            sums.push_back(sum);
            
            for (int i = 0; i < lines.size(); i++) {
                // single word or last line
                if (i == lines.size() -1 || lines[i].size() == 1) {
                    string a = "";
                    for (int j = 0; j < lines[i].size(); j++) {
                        if (a == "")
                            a = lines[i][j];
                        else
                            a += " " + lines[i][j];
                    }
                    a += makeSpaces(maxWidth - sums[i], 1, 0);
                    ans.push_back(a);
                }
                // distribute spaces
                else {
                    string a = "";
                    for (int j = 0; j < lines[i].size(); j++) {
                        if (a == "")
                            a = lines[i][j];
                        else
                            a += makeSpaces(maxWidth - sums[i], lines[i].size() - 1, j - 1) + lines[i][j];
                    }
                    ans.push_back(a);
                }
            }
            
            return ans;
        }
    };
    

    时间为55.19%,还可以,如果改为遍历一次会更快吧。

    相关文章

      网友评论

        本文标题:Leetcode刷题总结(2):字符串问题

        本文链接:https://www.haomeiwen.com/subject/qhykcftx.html