Leetcode-828. 统计子串中的唯一字符

链接

Leetcode-828. 统计子串中的唯一字符

题目

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

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

本题将会给你一个字符串 s ,我们需要返回 countUniqueChars(t) 的总和,其中 t 是 s 的子字符串。输入用例保证返回值为 32 位整数。

注意,某些子字符串可能是重复的,但你统计时也必须算上这些重复的子字符串(也就是说,你必须统计 s 的所有子字符串中的唯一字符)。

示例

示例 1:

输入: s = "ABC"
输出: 10
解释: 所有可能的子串为:"A","B","C","AB","BC" 和 "ABC"。
     其中,每一个子串都由独特字符构成。
     所以其长度总和为:1 + 1 + 1 + 2 + 2 + 3 = 10


示例 2:

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


示例 3:

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

说明

  • 1 <= s.length <= 10^5
  • s 只包含大写英文字符

思路

题目的意思就是给定一个字符串,求出这个字符串的所有子串的”唯一字符“的和。

我们先观察一个例子,比如某个字符串BBBACCADD,我们现在只考虑字母A在该字符串中对结果产生的影响,即可看成XXXAXXAXX。根据题意,只有当A在某个子串中有且仅有一个的时候,A才算作一个”唯一字符“,对结果的贡献为1,那么显然,如果一个子串中没有包含A(如子串BBB),或者包含了两个及以上的A(如子串BACCA),这个子串中的A无法使结果增加。因此,要求字母A对结果的贡献,我们只需要考虑有且仅有一个A的子串。

我们很容易可以想到,可以以A为分界线,分段计算,如对于刚才说的BBBACCADD这个字符串,我们假设有两个指针l和r,分别指向第一个A和第二个A。在起始的时候,l和r都指向-1,然后r往右走,遇到第一个字符B,不包含A,继续往右走,遇到第二个字符B,仍然不包含A,继续往右,此时遇到了第一个A,r更新3,此时l仍为初始时候的-1,对于目前左右指针里的字符BBBA,正好有3-(-1)=4个子串有且仅有1个A,对结果+4,即BBBA/BBA/BA/A,然后右指针r继续往右走,遇到了C,此时左右指针里的内容为BBBAC,而又正好新增了BBBAC/BBAC/BAC/AC,新增的个数仍未3-(-1)=4,注意r和l只有遇到A时才更新,然后r继续往右走,此时左右指针里的字符为BBBACC,这时新增了BBBACC/BBACC/BACC/ACC,也是贡献了4个。然后r继续往右走,这时候需要注意,r再次遇到了一个A,这时l将变成之前r的值(3),r则更新为当前这个A的下标6,这时左右指针里的内容为CCA,对结果的贡献为6-3=3,即CCA/CA/A,然后又像之前一样,重复以上过程。

也就是说对于A这个字符,我们计算他的贡献时只需要移动l和r这两个指针,遇到A就更新l和r的值,每次移动对结果的贡献都是r-l。由于s只包含26个大写字母,因此,只需要遍历26次,计算每每个字符对结果带来的贡献即可。

Java Code

class Solution {
    public int uniqueLetterString(String s) {
        int n = s.length();
        int res = 0;
        for(char c = 'A'; c<='Z'; c++){
            int l=-1, r=-1;
            for(int i=0; i

你可能感兴趣的:(Leetcode,leetcode,算法,数据结构)