Weekly Contest 83

1. 较大分组的位置

在一个由小写字母构成的字符串 S 中,包含由一些连续的相同字符所构成的分组。

例如,在字符串 S = "abbxxxxzyy" 中,就含有 "a", "bb", "xxxx", "z" 和 "yy" 这样的一些分组。

我们称所有包含大于或等于三个连续字符的分组为较大分组。找到每一个较大分组的起始和终止位置。

最终结果按照字典顺序输出。

示例 1:

输入: "abbxxxxzzy"
输出: [[3,6]]
解释: "xxxx" 是一个起始于 3 且终止于 6 的较大分组。

示例 2:

输入: "abc"
输出: []
解释: "a","b" 和 "c" 均不是符合要求的较大分组。

示例 3:

输入: "abcdddeeeeaabbbcd"
输出: [[3,5],[6,9],[12,14]]
说明:  1 <= S.length <= 1000

class Solution {
public:
    vector<vector<int>> largeGroupPositions(string S) {
        vector<vector<int>> ans;
        int start = 0;
        int size = S.size();
        while (start < size)
        {
            int j = start;
            for(; j < size & S[j] == S[start]; j++);
            if(j - start >= 3)
            {
                vector<int> tmp(2, -1);
                tmp[0] = start;
                tmp[1] = j-1;
                ans.push_back(tmp);
            }
            start = j;
        }
        return ans;
    }
};

2. 隐藏个人信息

给你一条个人信息 string S,它可能是一个邮箱地址,也可能是一个电话号码。

我们将隐藏它的隐私信息,通过如下规则: 

1. 电子邮箱

定义名称 是长度大于等于 2 (length ≥ 2),并且只包含小写字母 a-z 和大写字母 A-Z 的字符串。

电子邮箱地址由名称 开头,紧接着是符号 '@',后面接着一个名称 ,再接着一个点号 '.',然后是一个名称

电子邮箱地址确定为有效的,并且格式是 "name1@name2.name3"。

为了隐藏电子邮箱,所有的名称 必须被转换成小写的,并且第一个名称 的第一个字母和最后一个字母的中间的所有字母由 5 个 '*' 代替。 

2. 电话号码

电话号码是一串包括数字 0-9,以及 {'+', '-', '(', ')', ' '} 这几个字符的字符串。你可以假设电话号码包含 10 到 13 个数字。

电话号码的最后 10 个数字组成本地号码,在这之前的数字组成国际号码。注意,国际号码是可选的。我们只暴露最后 4 个数字并隐藏所有其他数字。

本地号码是有格式的,并且如 "--1111" 这样显示,这里的 1 表示暴露的数字。

为了隐藏有国际号码的电话号码,像 "+111 111 111 1111",我们以 "+--*-1111" 的格式来显示。在本地号码前面的 '+' 号和第一个 '-' 号仅当电话号码中包含国际号码时存在。例如,一个 12 位的电话号码应当以 "+-" 开头进行显示。

注意:像 "(",")"," " 这样的不相干的字符以及不符合上述格式的额外的减号或者加号都应当被删除。

最后,将提供的信息正确隐藏后返回。

示例 1:

输入: "LeetCode@LeetCode.com"
输出: "l*e@leetcode.com"
解释:
所有的名称转换成小写, 第一个名称的第一个字符和最后一个字符中间由 5 个星号代替。
因此,"leetcode" -> "l*e"。

示例 2:

输入: "AB@qq.com"
输出: "a*b@qq.com"
解释: 
第一个名称"ab"的第一个字符和最后一个字符的中间必须有 5 个星号
因此,"ab" -> "a*b"。

示例 3:

输入: "1(234)567-890"
输出: "--7890"
解释: 
10 个数字的电话号码,那意味着所有的数字都是本地号码。

示例 4:

输入: "86-(10)12345678"
输出: "+**---5678"
解释: 
12 位数字,2 个数字是国际号码另外 10 个数字是本地号码 。

注意:

S.length <= 40。
邮箱的长度至少是 8。
电话号码的长度至少是 10。

class Solution:
    def maskPII(self, S: str) -> str:
        # 判断是邮箱还是电话号码
        # 邮箱
        if '@' in S:
            tmp = S.lower()
            idx = tmp.index('@')
            front, after = tmp[:idx], tmp[idx:]
            return front[0] + '*' * 5 + front[-1] + after
        # 号码
        else:
            tmp = "".join(filter(str.isdigit, S))
            size = len(tmp)
            if size == 10:
                # 本地
                return "***-***-" + tmp[-4:]
            else:
                return "+" + "*" * (size-10) + "-***-***-" + tmp[-4:]

3. 连续整数求和

给定一个正整数 N,试求有多少组连续正整数满足所有数字之和为 N?

示例 1:

输入: 5
输出: 2
解释: 5 = 5 = 2 + 3,共有两组连续整数([5],[2,3])求和后为 5。

示例 2:

输入: 9
输出: 3
解释: 9 = 9 = 4 + 5 = 2 + 3 + 4

示例 3:

输入: 15
输出: 4
解释: 15 = 15 = 8 + 7 = 4 + 5 + 6 = 1 + 2 + 3 + 4 + 5
说明: 1 <= N <= 10 ^ 9

class Solution {
public:
    int consecutiveNumbersSum(int N) {
        int res = 0;
        for (int i = 1; i * (i - 1) / 2 < N; ++i) {
            if ((N - i * (i - 1) / 2) % i == 0) {
                ++res;
            }
        }
        return res;
    }
};

4. 统计子串中的唯一字符

我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符,并返回唯一字符的个数。

例如:s = "LEETCODE" ,则其中 "L", "T","C","O","D" 都是唯一字符,因为它们只出现一次,所以 countUniqueChars(s) = 5 。

本题将会给你一个字符串 s ,我们需要返回 countUniqueChars(t) 的总和,其中 t 是 s 的子字符串。注意,某些子字符串可能是重复的,但你统计时也必须算上这些重复的子字符串(也就是说,你必须统计 s 的所有子字符串中的唯一字符)。

由于答案可能非常大,请将结果 mod 10 + 9 + 7 后再返回。

示例 1:

输入: "ABC"
输出: 10
解释: 所有可能的子串为:"A","B","C","AB","BC" 和 "ABC"。

 其中,每一个子串都由独特字符构成。
 所以其长度总和为:1 + 1 + 1 + 2 + 2 + 3 = 10

示例 2:

输入: "ABA"
输出: 8
解释: 除了 countUniqueChars("ABA") = 1 之外,其余与示例 1 相同。

示例 3:

输入:s = "LEETCODE"
输出:92

提示:

0 <= s.length <= 10^4
s 只包含大写英文字符

C++ Version:

我来解释一下这个题的思路。

对每一个字符i,向前找到相同的字符j,向后找到相同的字符k。当前字符对最终结果的贡献是:(i-j)*(k-i)。

这相当于两种方案的拼接:在字符串A(j到i)当中,字符i贡献的次数是(i-j)次。在字符串B(k-i)当中,字符i贡献的次数是(k-i)。那么当两者拼接的时候,字符i对子串(j到k)的贡献就是两种方案的乘积(符合乘法公式)。

class Solution {
public:
    int uniqueLetterString(string s) {
        long sum = 0;
        int i, j, k;
        for(i = 0 ; i < s.size(); i++)
        {
            for(j = i - 1; j > -1 && s[j] != s[i]; j--);
            for(k = i + 1; k < s.size() && s[k] != s[i]; k++);
            sum += (i - j) * (k - i);
        }
        return sum % 1000000007;
    }
};
Last modification:March 19, 2020
如果觉得我的文章对你有用,请随意赞赏