第83场周赛

题目列表

最大分组的位置

链接: link.

本题所需语法知识介绍

vector容器:通常用vector< vector> >表示用容器来装容器
使用空的花括号 {} 可以方便地创建一个空的 vector,并在后续操作中通过下标访问其元素并为其赋值

class Solution {
public:
    vector<vector<int>> largeGroupPositions(string s) {
        vector<vector<int>> ret;
        int n = s.size();
        int num = 1;
        for (int i = 0; i < n; i++) {
            if (i == n - 1 || s[i] != s[i + 1]) {
                if (num >= 3) {
                    ret.push_back({i - num + 1, i});
                }
                num = 1;
            } else {
                num++;
            }
        }
        return ret;
    }
};

隐藏个人信息

链接: link.

本题所需语法知识介绍

  1. string::npos是一个静态成员常量,它是一个表示无效位置的特殊值
  2. if (at != string::npos)可以用来判断是否找到了字串
  3. 函数transform()接受四个参数:第一个参数是要转换的字符序列的开始位置,第二个参数是要转换的字符序列的结束位置,第三个参数是要将字符转换为的目标字符序列的开始位置,第四个参数是指示转换操作的函数对象。在这个例子中,第四个参数是::tolower,它是一个C++库函数,用于将单个字符转换为小写。因此,该行代码将transform()函数应用于s中的所有字符,将它们转换为小写字母
  4. ::tolower表示全局作用域下的tolower()函数,这是一个标准库函数
  5. s.substr(0, 1)是一个string类的成员函数,用于从字符串s的起始位置开始提取一个子字符串。它接受两个参数:第一个参数是要提取的子字符串的起始位置,第二个参数是要提取的子字符串的长度
  6. s.substr(at - 1)是一个string类的成员函数,用于从字符串s的指定位置开始提取子字符串。它接受一个参数,表示要提取的子字符串的起始位置。在这个例子中,at - 1是子字符串的起始位置,其中at是@符号在s中的位置,即电子邮件地址中用户名的结尾位置。因此,s.substr(at - 1)表示从字符串s的第at - 1个字符开始提取一个子字符串,即电子邮件地址中的域名部分
  7. 这句代码使用std::regex_replace()函数将字符串s中的所有非数字字符删除。std::regex_replace()函数是C++标准库函数,用于在字符串中进行正则表达式替换操作。它接受三个参数:第一个参数是要进行替换操作的原始字符串,第二个参数是一个正则表达式,用于匹配原始字符串中的子字符串,第三个参数是一个替换字符串,用于替换匹配到的子字符串。在这个例子中,第二个参数regex("[0-9]")是一个正则表达式,用于匹配所有非数字字符。[0-9]表示匹配除数字以外的任意字符。第三个参数是一个空字符串,因此所有匹配到的非数字字符都会被删除。最后,将删除后的字符串赋值给变量s,以便后续使用。
class Solution {
public:
   vector<string> country = {"", "+*-", "+**-", "+***-"};

   string maskPII(string s) {
       string res;
       int at = s.find("@");
       if (at != string::npos) {
           transform(s.begin(), s.end(), s.begin(), ::tolower);
           return s.substr(0, 1) + "*****" + s.substr(at - 1);
       }
       s = regex_replace(s, regex("[^0-9]"), "");
       return country[s.size() - 10] + "***-***-" + s.substr(s.size() - 4);
   }
};

连续整数求和

链接: link.

算法思路

如何可以整除i,那么说明一定有子序列为什么?因为n个i一定可以用不同的联系子序列表示出来,比如3个5可以用4+5+6来表示

int consecutiveNumbersSum(int N) {
  int res = 0;
  for (int i = 1; N > 0; N -= i++)
      res += (N % i == 0);
  return res;
}

统计子串中的唯一字符

链接: link.
算法思路:主打就是一个遍历加上累计
对于每个字母 i,遍历字符串 s,并在每个出现字母 i 的位置上记录 l 和 r,表示上一次出现字母 i 的位置和当前出现字母 i 的位置。
对于每个字母 i,其能构成的不同子串数量为其出现位置的区间 [l+1, r] 内的数字个数。
在遍历过程中,累加所有字母的子串数量,即可得到最终答案。
在第二步中,区间 [l+1, r] 内的数字个数可以用 r - l 计算得出,表示以 s[r] 结尾的子串数量。因此,累加所有字母的子串数量时,可以直接累加 r - l 的值,表示以当前字母结尾的子串数量。

需要注意的是,当 l=-1 时,表示此时为第一次出现字母 i,因此其能构成的子串数量为 r+1 个,而不是 r-l 个。因此,在记录 l 和 r 的初始值时,需要将其均初始化为 -1,而不是 0。

class Solution {
public:
  int uniqueLetterString(string s) {
      int n = s.length();
      long long ans = 0;
      for (char i = 'A'; i <= 'Z'; i++) {
          for (int j = 0, l = -1, r = -1; j < n; ++j) {
              if (s[j] == i) l = r, r = j;
              ans += r - l;
          }
      }
      return ans % 1000000007;
  }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值