0
点赞
收藏
分享

微信扫一扫

Node.js工程师养成计划

唯一字符常规乘法原理在统计子串中的应用

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

比如:s = "LEETCODE ",其中" l "、" t "、" c "、" o "、" d "是唯一字符,因为只出现一次,所以countUniqueChars(s) = 5。

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

请注意,有些子字符串可能是重复的,但是您还必须对这些重复的子字符串进行计数(也就是说,您必须对S的所有子字符串中的唯一字符进行计数)。

示例1:

Enter: 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:

Enter: s = "LEETCODE "


产量:92

复制代码

提示:


一个

s只包含大写的英文字符。


模拟+乘法原理


原问题是求所有子阵列的唯一字符之和,可以等价于求每个s[i]s[i]s[i]对答案的贡献,即每个s[I]s[I]s[I]s[I]可以充当多少个子阵列的唯一元素。

假设我们可以分别预处理两个数组L和R,这两个数组表示当s[i]s[i]s[i]是子数组的唯一字符时可以到达的最远端:


L[i] = a表示下标aaa为s[i]s[i]s[i]时最左边界可以是子数组的唯一字符,也就是s[i]s[i]s[i]左边第一个与s[i]s[i]相同的位置(不存在则为A =

R[i] = b表示跳转表bbb为s[i]s[i]s[i]时最右边界可以作为子数组的唯一字符,即S[I]S[I]S[I]S[I]S[I]右边第一个位置(如果不存在,则为b。


子阵列左端点数为(ia) (i-a) (ia),右端点数为(bi) (b-i) (bi)。根据乘法原理,子阵的个数是两者的乘积。

l和r只需要使用遍历计数进行预处理。

Java代码:

类别解决方案{

public int uniqueLetterString(String s){

char[]cs = s . tochararray();

int n = cs.length,ans = 0;

int[] l = new int[n],r = new int[n];

int[]CNTs = new int[26];

Arrays.fill(cnts,-1);

for(int I = 0;I < n;i++) {

int u = cs[I]-' A ';

l[I]= CNTs[u];

CNTs[u]= I;

}

Arrays.fill(cnts,n);

for(int I = n-1;I > = 0;我- ) {

int u = cs[I]-' A ';

r[I]= CNTs[u];

CNTs[u]= I;

}

for(int I = 0;I < n;i++)ans+=(I-l[I])*(r[I]-I);

返回ans

}

}

复制代码

类型脚本代码:

function uniqueLetterString(s:string):number {

设n = s.length,ans = 0

const l =新数组(n),r =新数组(n)

const cnts =新数组(26)。填充(-1)

for(设I = 0;I < n;i++) {

const u = s.charCodeAt(i) - 65

l[i] = cnts[u]

cnts[u] = i

}

cnts.fill(n)

for(设I = n-1;I > = 0;我- ) {

const u = s.charCodeAt(i) - 65

r[i] = cnts[u]

cnts[u] = i

}

for(设I = 0;I < n;i++) ans += (i - l[i]) * (r[i] - i)

返回答案

};

复制代码


时间复杂度:O(n)O(n)O(n)

空间复杂度:O(n)O(n)O(n)

Node.js工程师养成计划download:http://www.51xuebc.com/thread-447-1-1.html

举报

相关推荐

0 条评论