• [LeetCode] 828. Count Unique Characters of All Substrings of a Given String


    Let's define a function countUniqueChars(s) that returns the number of unique characters on s.

    • For example, calling countUniqueChars(s) if s = "LEETCODE" then "L""T""C""O""D" are the unique characters since they appear only once in s, therefore countUniqueChars(s) = 5.

    Given a string s, return the sum of countUniqueChars(t) where t is a substring of s. The test cases are generated such that the answer fits in a 32-bit integer.

    Notice that some substrings can be repeated so in this case you have to count the repeated ones too.

    Example 1:

    Input: s = "ABC"
    Output: 10
    Explanation: All possible substrings are: "A","B","C","AB","BC" and "ABC".
    Every substring is composed with only unique letters.
    Sum of lengths of all substring is 1 + 1 + 1 + 2 + 2 + 3 = 10
    

    Example 2:

    Input: s = "ABA"
    Output: 8
    Explanation: The same as example 1, except countUniqueChars("ABA") = 1.
    

    Example 3:

    Input: s = "LEETCODE"
    Output: 92

    Constraints:

    • 1 <= s.length <= 105
    • s consists of uppercase English letters only.

    统计子串中的唯一字符。

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

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

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

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

    来源:力扣(LeetCode)
    链接:https://leetcode.cn/problems/count-unique-characters-of-all-substrings-of-a-given-string
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    首先我们看一下暴力解。对于 input 字符串,我们需要找到他所有长度不同的子串,这个时间复杂度就是O(n^2),我们还要看一下每个子串内只出现一次的字母有几个,这个复杂度是O(n),总体复杂度是O(n^3)。

    这里我提供一个很巧妙的做法,我参考了这个帖子。与其去找不同子串并计算不同子串里 unique 的字母个数是多少,我们可以反过来思考,对于每个字母而言,我们可以去计算包含这个字母且这个字母只出现一次的子串有多少。只有保证当前字母只出现一次,才满足题目中 countUniqueChars() 函数的定义。

    对于任意一个字母,在 input 字符串中很可能是出现了多次的。假如对于我们当前遇到的字母 X,如果我们能找到 X 在 input 字符串中上一次出现的位置 j 和下一次出现的位置 k,那么包含当前位置 i 且满足题意的子串个数应该是 (i - j) * (k - i)。

    具体做法如下。我创建了一个二维数组,需要记录每个字母前两次出现位置的 index。开始遍历 input 字符串,当遇到某个字母的时候,我们把当前位置当做 k,我们去二维数组里看一下是否存在 index i 和 j,如果存在,我们就按照上面那个公式去计算一下包含当前位置上字母的子串有多少。

    时间O(n)

    空间O(n)

    Java实现

     1 class Solution {
     2     public int uniqueLetterString(String s) {
     3         int MOD = (int) Math.pow(10, 9) + 7;
     4         int len = s.length();
     5         int res = 0;
     6         int[][] index = new int[26][2];
     7         for (int i = 0; i < 26; i++) {
     8             Arrays.fill(index[i], -1);
     9         }
    10         
    11         for (int i = 0; i < len; i++) {
    12             int c = s.charAt(i) - 'A';
    13             res = (res + (i - index[c][1]) * (index[c][1] - index[c][0]) % MOD) % MOD;
    14             index[c] = new int[] {index[c][1], i};
    15         }
    16         for (int c = 0; c < 26; c++) {
    17             res = (res + (len - index[c][1]) * (index[c][1] - index[c][0]) % MOD) % MOD;
    18         }
    19         return res;
    20     }
    21 }

    LeetCode 题目总结

  • 相关阅读:
    05 库的简单操作
    04 基本的MySQL语句
    03 MySQL安装和基本管理
    02 数据库概述
    01 MySQL入门了解
    Django-组件拾遗
    bootstrap基础讲解
    jQuery练习
    前端基础之Jquery
    15 Django组件-中间件
  • 原文地址:https://www.cnblogs.com/cnoodle/p/16468617.html
Copyright © 2020-2023  润新知