leetcode 计算贡献题

  • 6050. 字符串的总引力
  • 828. 统计子串中的唯一字符
  • 907. 子数组的最小值之和
  • 1498. 满足条件的子序列数目
  • 2104. 子数组范围和

6050. 字符串的总引力

1. 题目

字符串的 引力 定义为:字符串中 不同 字符的数量。

  • 例如,"abbca" 的引力为 3 ,因为其中有 3 个不同字符 'a'、'b' 和 'c' 。
    给你一个字符串 s ,返回 其所有子字符串的总引力 。

子字符串 定义为:字符串中的一个连续字符序列。

示例 1:

输入:s = "abbca"
输出:28
解释:"abbca" 的子字符串有:
- 长度为 1 的子字符串:"a"、"b"、"b"、"c"、"a" 的引力分别为 1、1、1、1、1,总和为 5 。
- 长度为 2 的子字符串:"ab"、"bb"、"bc"、"ca" 的引力分别为 2、1、2、2 ,总和为 7 。
- 长度为 3 的子字符串:"abb"、"bbc"、"bca" 的引力分别为 2、2、3 ,总和为 7 。
- 长度为 4 的子字符串:"abbc"、"bbca" 的引力分别为 3、3 ,总和为 6 。
- 长度为 5 的子字符串:"abbca" 的引力为 3 ,总和为 3 。
引力总和为 5 + 7 + 7 + 6 + 3 = 28 。
示例 2:

输入:s = "code"
输出:20
解释:"code" 的子字符串有:
- 长度为 1 的子字符串:"c"、"o"、"d"、"e" 的引力分别为 1、1、1、1 ,总和为 4 。
- 长度为 2 的子字符串:"co"、"od"、"de" 的引力分别为 2、2、2 ,总和为 6 。
- 长度为 3 的子字符串:"cod"、"ode" 的引力分别为 3、3 ,总和为 6 。
- 长度为 4 的子字符串:"code" 的引力为 4 ,总和为 4 。
引力总和为 4 + 6 + 6 + 4 = 20 。

提示:

  • 1 <= s.length <= 105
  • s 由小写英文字母组成

2. 解题思路

2.1 题意理解&公式化表达

设为字符串的吸引力,则题目可以转化为:已知字符串,求。

首先,我们来看一下这个公式的复杂度:外层双循环为;内层,如果采用遍历字符串中元素的方法,那么是。因而总体复杂度为,一下子就超时了。

那应该怎么优化呢?Let's 画图思考!

2.2 使用双计数原理进行优化

我们依然保持外层循环不变,看一下可以如何优化里面的公式。

s='abbca'为例,当i=0时,我们可以画出如下示意图。其中,横向代表j的取值,纵向代表26个小写字母,方格为1代表s[i:j+1]中包含该字母。那么,以i=0为起点的所有子串的吸引力值=矩阵中1的个数。

矩阵示意图

如果我们对矩阵纵向求和,相当于对j进行遍历,正好对应前述公式。

纵向求和

根据双计数原理,我们还可以横向计数呀。我们对字符进行遍历,也可以对矩阵进行求和。那每行1的个数如何计算呢?其实就等于n-该字符第一次出现的索引值!

这个索引怎么求?一句话,反向遍历!只要i是反向遍历,那么每个字符都只需要记录最近一次出现的索引。

横向求和

2.3 复杂度分析

  • 时间复杂度:。为字符集大小
  • 空间复杂度:

3. 代码

class Solution:
    def appealSum(self, s: str) -> int:
        n = len(s)
        li = [-1] * 26
        res = 0
        for i in range(n-1, -1, -1):
            li[ord(s[i]) - ord('a')] = i
            for idx in li:
                if idx != -1:
                    res += n - idx
        return res

你可能感兴趣的:(leetcode 计算贡献题)