Java实现 LeetCode 828 统计子串中的唯一字符(暴力+转数组)

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

我们定义了一个函数 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 只包含大写英文字符

class Solution {
    /*
    大佬的解释(比官方的解释🐂🍺)
    对每一个字符i,向前找到相同的字符j,向后找到相同的字符k。当前字符对最终结果的贡献是:(i-j)*(k-i)。

这相当于两种方案的拼接:在字符串A(j到i)当中,字符i贡献的次数是(i-j)次。在字符串B(k-i)当中,字符i贡献的次数是(k-i)。那么当两者拼接的时候,字符i对子串(j到k)的贡献就是两种方案的乘积(符合乘法公式)。
    */
      public int uniqueLetterString(String s) {
        char[] cs = s.toCharArray();
        int size = cs.length;
        int[][] pos = new int[26][2];
        for (int i = 0; i < 26; i++) {
            pos[i][0] = pos[i][1] = -1;
        }
        long ans = 0;

        for (int i = 0; i < size; i++) {
            int c = cs[i] - 'A';
            int[] curpos = pos[c];
            if ( curpos[0] != -1 || curpos[1] != -1 ) {
                ans += (i-curpos[1]) * (curpos[1]-curpos[0]);
            }
            curpos[0] = curpos[1];
            curpos[1] = i;
        }

        for (int i = 0; i < 26; i++) {
            int[] curpos = pos[i];
            if (curpos[0] != -1 || curpos[1] != -1) {
                ans += (size-curpos[1]) * (curpos[1]-curpos[0]);
            }
        }

        return (int)(ans % 1000000007);
    }
 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章