Java C++ 算法leetcode828统计子串中唯一字符乘法原理
作者:AnjaVon 发布时间:2022-05-09 11:19:18
标签:Java,C++,算法,子串唯一字符,乘法原理
题目要求
思路:模拟
解题的核心思想在于逆向思维,不考虑每个子数组中的唯一字符个数,转而考虑每个字符可以作为多少个子数组的唯一字符;
所以在计算答案时的算式和示例中给出的是不一样的;
在计算每个字符“贡献”【即当前向左向右分别可组成的答案个数】的时候要用到乘法原理。
对每一个字符s[i]s[i]s[i]都记录其左边和右边的第一个相同字符位置,分别记为l[i]l[i]l[i]和r[i]r[i]r[i],这两个位置中间构成的就是s[i]s[i]s[i]能够作为唯一字符的最长子串,在这个最长的子串中还有若干个较短的子串,此时s[i]s[i]s[i]的“贡献”可由到左边和到右边的距离相乘计算得出。
java
class Solution {
public int uniqueLetterString(String s) {
char[] cs = s.toCharArray();
int n = cs.length, res = 0;
int[] l = new int[n], r = new int[n];
int[] letters = new int[26];
Arrays.fill(letters, -1);
for (int i = 0; i < n; i++) {
int idx = cs[i] - 'A';
l[i] = letters[idx]; // 左边第一个相同的字符所在位置
letters[idx] = i; // 更新当前字母最新左位置
}
Arrays.fill(letters, n);
for (int i = n - 1; i >= 0; i--) {
int idx = cs[i] - 'A';
r[i] = letters[idx]; // 右边第一个相同的字符所在位置
letters[idx] = i; // 更新当前字母最新右位置
}
for (int i = 0; i < n; i++)
res += (i - l[i]) * (r[i] - i);
return res;
}
}
时间复杂度:O(n)
空间复杂度:O(n)
C++
因为
memset
初始化问题,所以在构成结果的时候多一步判断。
class Solution {
public:
int uniqueLetterString(string s) {
int n = s.size(), res = 0;
cout << n << endl;
int l[n], r[n];
int letters[26];
memset(letters, -1, sizeof(letters));
for (int i = 0; i < n; i++) {
int idx = s[i] - 'A';
l[i] = letters[idx]; // 左边第一个相同的字符所在位置
letters[idx] = i; // 更新当前字母最新左位置
}
memset(letters, -1, sizeof(letters));
for (int i = n - 1; i >= 0; i--) {
int idx = s[i] - 'A';
r[i] = letters[idx]; // 右边第一个相同的字符所在位置
letters[idx] = i; // 更新当前字母最新右位置
}
for (int i = 0; i < n; i++) {
int ri = r[i] == -1 ? n : r[i];
res += (i - l[i]) * (ri - i);
}
return res;
}
};
时间复杂度:O(n)
空间复杂度:O(n)
Rust
用Rust的遍历稍微改一下,思路一样……
impl Solution {
pub fn unique_letter_string(s: String) -> i32 {
let cs = s.as_bytes();
(0..s.len()).into_iter().map(|i| {
let (mut l, mut r) = (i - 1, i + 1);
while l < s.len() && cs[l] != cs[i] {
l -= 1;
}
while r < s.len() && cs[r] != cs[i] {
r += 1;
}
((i - l) * (r - i)) as i32
}).sum::<i32>()
}
}
时间复杂度:O(n)
空间复杂度:O(n)
来源:https://juejin.cn/post/7140264367676719117
0
投稿
猜你喜欢
- 我们知道,进入百度图片后,输入一个关键字后,首先看到的是很多缩略图,当我们点击某张缩略图时,我们就可以进入到大图显示页面,在大图显示页面,中
- 反射方式获取JPA Entity属性和值在记录日志或者调试的时候,往往需要输出数据库查询或者写入的值,或者在接 * 互的时候,可能需要将实体转
- 现在的项目基本上都是java web项目,所以导入jar包会出现问题,主要介绍一下java项目与javaweb项目的区别:java项目:在c
- 本文实例总结了MFC程序设计常用技巧。分享给大家供大家参考。具体如下:1.属性页的添加:创建对话框的类,该类要从CpropertyPage继
- 在线程中有两种常用的方法,能够通过数组实现相应的功能,但除此之外在区别上也是很明显的。本篇就其中的代表方法ArrayList和Vector进
- CSRF介绍CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click atta
- 一个围绕统计分析功能的系统,在最后制作统计分析时需要一个批量点击的功能,用以批量制作echarts图形后生成图片并保存图形和图片。方便后续导
- 这是Hadoop学习全程记录第1篇,在这篇里我将介绍一下如何在Linux下安装Hadoop1.x。先说明一下我的开发环境:虚拟机:VMwar
- 在使用struts多模块的,找到一些小技巧和经验,与大家分享一下。 关于多module的配置就不说了,只需要用不同的config
- 接收到这样一个需求,就是英文名字中firstName和lastName,其中任何一个为null,就返回Empty。刚拿到需求,这不简单,if
- 过滤器实现过滤器需要实现 javax.servlet.Filter 接口。重写三个方法。其中 init() 方法在服务启动时执行,destr
- 1. 为什么要进行参数校验在后端进行工作时,需要接收前端传来的数据去数据库查询,但是如果有些数据过于离谱,我们就可以直接把它pass掉,不让
- 详解java中的PropertyChangeSupport与PropertyChangeListenerjava中的PropertyChan
- 个人理解:把一个类里的多个命令分离出来,每个类里放一个命令,实现解耦合,一个类只对应一个功能,在使用命令时由另一个类来统一管理所有命令。缺点
- 最近有个项目的几张表,数量级在千万以上,技术栈是SpringBoot+Mybatis-plus+MySQL。如果使用单表,在进行查询操作,非
- 各位亲们可以尝试以下代码:注:这里我就只有一个html标签对来说明问题了,首部之类的东西,自己添加。<html> &n
- Java实现按行读取大文件String file = "F:" + File.separator + "a.t
- 1. 前言在Java开发中接触的开发者大多数不太注重对接口的测试,结果在联调对接中出现各种问题。也有的使用Postman等工具进行测试,虽然
- 概述不知道大家在平时的开发过程中或者源码里是否留意过内部类,那有思考过为什么要有内部类,内部类都有哪几种形式,静态内部类和普通内部类有什么区
- 概述:Spring Boot 2.0相对于之前的版本,变化还是很大的。首先对jdk的版本要求已经不能低于1.8,其次依赖的spring的版本