力扣做题记录——290.单词规律&763.划分字母区间

290.单词规律
给定一种规律pattern和一个字符串str,判断str是否遵循相同的规律。
这里的遵循指完全匹配,例如,pattern里的每个字母和字符串str中的每个非空单词之间存在着双向连接的对应规律。
示例1

输入: pattern = "abba", str = "dog cat cat dog"
输出: true

示例2

输入:pattern = "abba", str = "dog cat cat fish"
输出: false

示例3

输入: pattern = "aaaa", str = "dog cat cat dog"
输出: false

提示

  • 1 <= pattern.length <= 300
  • pattern只包含小写英文字母
  • 1 <= str.length <= 3000
  • str只包含小写英文字母和 ' '
  • str不包含 任何前导或尾随对空格
  • str中每个单词都被单个空格分隔

思路
这道题的关键在于如何构建pattern中字符和str中单词的双向映射,这个双向映射能够保证一个字符对应一个单词,一个单词也只对应一个字符。可以用双哈希表来表示这种关系,即hashmap1[i] = jhashmap2[j] = i
代码

bool wordPattern(string pattern, string str) {
    unordered_map<string, char> str2ch;
    unordered_map<char, string> ch2str;
    int m = str.length();
    int i = 0;
    // 逐个遍历模式串
    for (auto ch : pattern) {
        if (i > m) {
            return false;
        }
        // 划分单词
        int j = i;
        while (j < m && str[j] != ' ') j++;
        const string &tmp = str.substr(i, j - i);
        // 如果以单词为键值的哈希表中存在tmp对应的值且这个值不等于当前字符,返回false
        if (str2ch.count(tmp) && str2ch[tmp] != ch) {
            return false;
        }
        // 如果以字符为键值的哈希表中存在ch对应的值且这个值不等于当前单词,返回false
        if (ch2str.count(ch) && ch2str[ch] != tmp) {
            return false;
        }
        // 这两句指令是为了初始化哈希表
        str2ch[tmp] = ch;
        ch2str[ch] = tmp;
        i = j + 1;
    }
    return i > m;
}

763.划分字母区间
字符串s由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
示例

输入:S = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少

提示

  • s的长度在[1, 500]之间。
  • s只包含小写字母'a''z'

思路
由于同一个字母只能出现在同一个字段,因此同一个字母的第一次出现的下标位置和最后一次出现的下标位置必须出现在同一个片段。因此需要遍历字符串,得到每一个字母最后一次出现的下标位置。

  • 从左到右遍历字符串,遍历的同时维护当前片段的开始下标 s t a r t start start和结束下标 e n d end end,初始条件 s t a r t = e n d = 0 start=end=0 start=end=0
  • 对于每个遍历到的字母 c c c,得到当前字母的最后一次出现的下标位置 e n d c end_c endc,则当前片段的结束下标一定不小于 e n d c end_c endc,因此令 e n d = m a x ( e n d , e n d c ) end=max(end, end_c) end=max(end,endc)
  • 当访问到下标 e n d end end时,本片段访问结束,当前片段的下标范围是 [ s t a r t , e n d ] [start,end] [start,end],长度为 e n d − s t a r t + 1 end-start+1 endstart+1,将当前片段的长度加入返回值中,然后令 s t a r t = e n d + 1 start=end + 1 start=end+1

代码

vector<int> partitionLabels(string s) {
    vector<int> result;
    unordered_map<char, int> map; //记录char c 和其最后出现位置的 map
    int start = 0, end = 0;
    for (int i = 0; i < s.size(); i ++) {
        map[s[i]] = i;
    }
    for (int i = 0; i < s.size(); i ++) {
        end = max(end, map[s[i]]);
        if (i == end) {
            result.push_back(end - start + 1);
            start = i + 1;
        }
    }
	return result;
}

本文题目及部分解答来自力扣:290.单词规律763.划分字母区间

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值