leetcode820.单词的压缩编码

由于最近在准备各个企业的笔试,以及一些相关的东西,所以需要提高编程能力,就开始刷leetcode,慢慢来吧,一边来一边整理。

题目:
给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A。
例如,如果这个列表是 [“time”, “me”, “bell”],我们就可以将其表示为 S = “time#bell#” 和 indexes = [0, 2, 5]。
对于每一个索引,我们可以通过从字符串 S 中索引的位置开始读取字符串,直到 “#” 结束,来恢复我们之前的单词列表。
那么成功对给定单词列表进行编码的最小字符串长度是多少呢?

示例:

输入: words = ["time", "me", "bell"]
输出: 10
说明: S = "time#bell#" , indexes = [0, 2, 5]

一开始拿到题目,不太理解这是什么意思,于是去看了题解,按照大佬的题解进行理解就明白了。

time索引是在S位置0,me索引是在S位置2,bell索引是在位置5

**题意理解及思路:**如果有一对单词 s 和 t,使得 t 是 s 的后缀,例如 me 是 time 的后缀,我们就删掉单词 t。最后剩下来的单词,就是构成索引字符串的单词。我们需要找到单词字母数最少为多少。而在找到最小值的时候,我们可以通过进行排序来进行判断,检查排序后的每一个单词,如果当前单词是下一个单词的前缀,则将单词丢弃,如果不是的话,那就结果+当前单词长度+1(#的位置)。

于是可以得到第一版本的代码:

代码和思路均按照大佬的题解来的,在本博客仅为自己的学习笔记,解释了一些不熟悉的函数、用法以及整理个人思路等。

int minimumLengthEncoding(vector<string>& words) {
    int N = words.size();
    // 反转每个单词
    vector<string> reversed_words;
    for (string word : words) {
        reverse(word.begin(), word.end());
        reversed_words.push_back(word);
    }
    // 字典序排序    
    sort(reversed_words.begin(), reversed_words.end());

    int res = 0;
    for (int i = 0; i < N; i++) {
        if (i+1 < N && reversed_words[i+1].find(reversed_words[i]) == 0) {
            // 当前单词是下一个单词的前缀,丢弃
        } else {
            res += reversed_words[i].length() + 1; // 单词加上一个 '#' 的长度
        }
    }
    return res;
}

for (string word : words)
这一句代码没有仔细查,有点像python哈哈哈,但是应该是vector的用法吧

reverse函数
reverse()函数可以对字符串进行反转操作,头文件是#include< algorithm>
容器类型的要用begin()和end()来指定反转的区域,数组类型的直接用int类型即可
因为在题目中使用的是string,所以需要使用begin和end(???是因为string算是一种容器吗)

push_back函数
push_back为在vector容器最后添加一个值

sort函数
默认升序排序,包含在头文件为#include< algorithm>中
Sort(start,end,cmp)
参数:
(1)start表示要排序数组的起始地址;
(2)end表示数组结束地址的下一位;
(3)cmp用于规定排序的方法,可不填,默认升序。
第三个参数的用法:附加一个函数,如下即实现了一个降序排列,对于自己定义的类或自己定义的判定大小方法即可用外加函数来实现。

bool compare(int a,int b)
{
    return a>b;
}
sort(a,a+10,compare);

然后再得到了这第一种的代码之后,大佬还是不满意,因为有了一个数组就有了额外的空间消耗,所以大佬提出,“既然你知道了这怎么回事啦,那就直接从后向前排吧!”
fine

//从后向前进行比较
static bool compare(string& s1, string& s2) {
    int N1 = s1.length();
    int N2 = s2.length();
    for (int i = 0; i < min(N1, N2); i++) {
        char c1 = s1[N1-1-i];
        char c2 = s2[N2-1-i];
        if (c1 != c2) {
            return c1 < c2;
        }
    }
    return N1 < N2;
}

int minimumLengthEncoding(vector<string>& words) {
    int N = words.size();
    // 逆序字典序排序    
    sort(words.begin(), words.end(), compare);//就像上面对compare函数的讲解一样,附加函数

    int res = 0;
    for (int i = 0; i < N; i++) {
        if (i+1 < N && endsWith(words[i+1], words[i])) {
            // 当前单词是下一个单词的后缀,丢弃
        } else {
            res += words[i].length() + 1; // 单词加上一个 '#' 的长度
        }
    }
    return res;
}
//判断是否是后缀
bool endsWith(string& s, string& t) {
    int N1 = s.length();
    int N2 = t.length();
    if (N1 < N2) {
        return false;
    }
    for (int i = 0; i < N2; i++) {
        if (s[N1-N2+i] != t[i]) {
            return false;
        }
    }
    return true;
}

刷leetcode第一天,感觉大佬真的好厉害!

你可能感兴趣的:(C++,leetcode,学习笔记)