前言
为啥没毕业也有论文抽检,害得我昨天改了一天论文.....
练习
隐藏个人信息
给你一条个人信息字符串 s ,可能表示一个 邮箱地址 ,也可能表示一串 电话号码 。返回按如下规则 隐藏 个人信息后的结果:
电子邮件地址:
一个电子邮件地址由以下部分组成:
一个 名字 ,由大小写英文字母组成,后面跟着
一个 '@' 字符,后面跟着
一个 域名 ,由大小写英文字母和一个位于中间的 '.' 字符组成。'.' 不会是域名的第一个或者最后一个字符。
要想隐藏电子邮件地址中的个人信息:
名字 和 域名 部分的大写英文字母应当转换成小写英文字母。
名字 中间的字母(即,除第一个和最后一个字母外)必须用 5 个 "*****" 替换。
电话号码:
一个电话号码应当按下述格式组成:
电话号码可以由 10-13 位数字组成
后 10 位构成 本地号码
前面剩下的 0-3 位,构成 国家代码
利用 {'+', '-', '(', ')', ' '} 这些 分隔字符 按某种形式对上述数字进行分隔
要想隐藏电话号码中的个人信息:
移除所有 分隔字符
隐藏个人信息后的电话号码应该遵从这种格式:
"***-***-XXXX" 如果国家代码为 0 位数字
"+*-***-***-XXXX" 如果国家代码为 1 位数字
"+**-***-***-XXXX" 如果国家代码为 2 位数字
"+***-***-***-XXXX" 如果国家代码为 3 位数字
"XXXX" 是最后 4 位 本地号码
示例 1:
输入:s = "LeetCode@LeetCode.com"
输出:"l*****e@leetcode.com"
解释:s 是一个电子邮件地址。
名字和域名都转换为小写,名字的中间用 5 个 * 替换。
示例 2:
输入:s = "AB@qq.com"
输出:"a*****b@qq.com"
解释:s 是一个电子邮件地址。
名字和域名都转换为小写,名字的中间用 5 个 * 替换。
注意,尽管 "ab" 只有两个字符,但中间仍然必须有 5 个 * 。
示例 3:
输入:s = "1(234)567-890"
输出:"***-***-7890"
解释:s 是一个电话号码。
共计 10 位数字,所以本地号码为 10 位数字,国家代码为 0 位数字。
因此,隐藏后的电话号码应该是 "***-***-7890" 。
示例 4:
输入:s = "86-(10)12345678"
输出:"+**-***-***-5678"
解释:s 是一个电话号码。
共计 12 位数字,所以本地号码为 10 位数字,国家代码为 2 位数字。
因此,隐藏后的电话号码应该是 "+**-***-***-7890" 。
提示:
s 是一个 有效 的电子邮件或者电话号码
如果 s 是一个电子邮件:
8 <= s.length <= 40
s 是由大小写英文字母,恰好一个 '@' 字符,以及 '.' 字符组成
如果 s 是一个电话号码:
10 <= s.length <= 20
s 是由数字、空格、字符 '('、')'、'-' 和 '+' 组成
class Solution {
String[] country = {"", "+*-", "+**-", "+***-"};
public String maskPII(String s) {
int at = s.indexOf("@");//如果是字母就有@反正就是数字
if (at > 0) {//有@就是字母,这是一个判断, 没有@就不会>0,所以会直接执行s
s = s.toLowerCase();//将大写字母转换成小写
return (s.charAt(0) + "*****" + s.substring(at - 1)).toLowerCase();
}
s = s.replaceAll("[^0-9]", "");//replaceAll全替换 (将不是数字的)都替换为空
//[^0-9] 非数字替换 [0-9]数字替换
return country[s.length() - 10] + "***-***-" + s.substring(s.length() - 4);
}
}
class Solution {
public String maskPII(String s) {
if (Character.isLetter(s.charAt(0))) {//判断是不是字母,是就返回真
s = s.toLowerCase();//转换大写字母变小写字母
int i = s.indexOf('@');
return s.substring(0, 1) + "*****" + s.substring(i - 1);
}
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
if (Character.isDigit(c)) {//判断是不是数字 是就返回真
sb.append(c);
}
}
s = sb.toString();
int cnt = s.length() - 10;
String suf = "***-***-" + s.substring(s.length() - 4);
return cnt == 0 ? suf
: "+"
+ "*".repeat(cnt) + "-" + suf;//repeat重复记录几次
}
}
class Solution {
public String maskPII(String s) {
int index = s.indexOf("@");
if (index == -1) {
int cnt = 0;
char sc[] = new char[13];
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c <= '9' && c >= '0') {
sc[cnt] = c;
cnt++;
}
}
StringBuilder sb = new StringBuilder();
if (cnt == 10) {
sb.append("***-***-");
sb.append(new String(sc, 6, 4));
} else if (cnt == 11) {
sb.append("+*-***-***-");
sb.append(new String(sc, 7, 4));
} else if (cnt == 12) {
sb.append("+**-***-***-");
sb.append(new String(sc, 8, 4));
} else if (cnt == 13) {
sb.append("+***-***-***-");
sb.append(new String(sc, 9, 4));
}
return sb.toString();
} else {
char sc[] = s.toCharArray();
StringBuilder sb = new StringBuilder();
if (sc[0] >= 'A' && sc[0] <= 'Z') {
sb.append((char) (sc[0] - 'A' + 'a'));
} else {
sb.append(sc[0]);
}
// System.out.println(index);
for (int i = 0; i <5; i++) {
// System.out.println(i);
sb.append('*');
}
if (sc[index-1] >= 'A' && sc[index-1] <= 'Z') {
sb.append((char) (sc[index-1] - 'A' + 'a'));
} else {
sb.append(sc[index-1]);
}
sb.append('@');
for (int i = index + 1; i < sc.length; i++) {
if (sc[i] >= 'A' && sc[i] <= 'Z') {
sb.append((char) (sc[i] - 'A' + 'a'));
} else {
sb.append(sc[i]);
}
}
return sb.toString();
}
}
}
补习班的朋友说我做算法题,一会一个枚举,一会一个数组,一会一个正则,可乱,而且不利于我学习,建议我逮住一个练个五六道再换,我想了想,有点道理,但是我对自己的信心不是很足,不过还是按着朋友的建议来吧,明天开始。
另外本题思路
就只有一个意思,两种大情况,一种是全电子邮箱,也就是全字母,一个是全电话号,也就是全数字。而且中间还要*****跟@,少不了正则表达,不过我也贴了个0ms大神的代码,全模拟,没用上正则,用正则的速度慢,有利有弊吧,至少要修改代码的时候,正则好修改一点
第一次感觉官方代码更容易理解(第一个代码)第二个代码是Y神(我经常去看他的代码)第三个就算找了个用时最快的大神代码。本身不是很难理解,关键是自己没用过,知道是正则,但是自己不会写,真是自己写,我估计跟第三个一样,写一堆if-else来判断那个国家代码,大神都想到用数组了,而且我看见数字脑子就蹦出来/d了
因为官方的解释太容易理解了,就直接借用了
我们首先判断 sss 是邮箱还是电话号码。显然,如果 sss 中有字符 ‘@’\text{`@'}‘@’,那么它是邮箱,否则它是电话号码。
如果 sss 是邮箱,我们将 sss 的 ‘@’\text{`@'}‘@’ 之前的部分保留第一个和最后一个字符,中间用 “*****"\text{``*****"}“*****" 代替,并将整个字符串转换为小写。
如果 sss 是电话号码,我们只保留 sss 中的所有数字。使用首先将最后 101010 位本地号码变成 “***-***-XXXX"\text{``***-***-XXXX"}“***-***-XXXX" 的形式,再判断 sss 中是否有额外的国际号码。如果有,则将国际号码之前添加 ‘+’\text{`+'}‘+’ 号并加到本地号码的最前端。
如果有 101010 位数字,则加上前缀位空字符串。
如果有 111111 位数字,则加上前缀 “+*-"\text{``+*-"}“+*-"。
如果有 121212 位数字,则不加上前缀 “+**-"\text{``+**-"}“+**-"。
如果有 131313 位数字,则不加上前缀 “+**"\text{``+**"}“+**"。
八股
mysql搜索引擎之平衡二叉树AVLTree的问题
平衡二叉树的问题在于维护成本过高,每次删除一个节点或者增加一个节点都需要多次左旋右旋去维护平衡,且查询效率低,带有运气成分,而且树的节点越多,树就越高,查询效率越低
而且最主要的是树的IO磁盘问题,二叉树最差的情况就是递增或递减,这种类似的情况就会成为全部遍历,这样的问题说明节点存储数据太少,没有很好利用操作系统和磁盘数据的交换,所以查询效率低,不适合作为 mysql的查询结构
解决方法:通过降低树的高度达到减少IO的次数
mysql搜索引擎之B树BTree
b树又称为2-3树,也就是b树上的节点可能是2也可能是3
b树的原理其实很简单,真实数据会占用大量内存,因此需要索引来管理这些真实数据,而这些索引就是树的节点,也就是说对应的磁盘页就是索引树的节点,而系统读取页是以磁盘块为单位的,索引一个页里面的块会被一次性读出来,而查询时就直接以页的单位查询,减少了IO次数,提高效率
b树对比平衡二叉树少了一些IO操作,因为b树比二叉树缩减了节点个数,提升了效率
mysql搜索引擎之B+树
b+树吧索引数据放在子节点,形成链表,查数据更方便(好查,方便排序,规划范围)
所以说b+树的精髓就是树+链表 子节点之间有指针指向,这样查找范围更大,而且数据只存在同一层子节点上,节点之间增加链表,获取索引节点,不需要再遍历
原理是非叶子节点只存储键值信息,假设每个磁盘块可以存4个键值和指针信息,那么每一节点不仅包含数据的key值还有data值,而每一页的存储空间有限,数据越大,key存的就越少,b树的深度就越大,查询的io次数就越多,速度就越慢,从而影响查询效率
mysql为什么选择之B+树
B+树中,所有数据记录节点都是按照键值大小顺序存放在同一层叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+树的高度。
innodb存储引擎最小存储单元是页,所以可以存放键值对和指针,转换成b+树就是叶子节点存数据,非叶子节点存放键值+指针,而对应的索引通过非叶子节点二分查找和指针确定数据在那个页里,从根页开始找数据页
B+树算法:通过集成B树的特征,B+树相比B树,新增叶子节点与非叶子节点关系,叶子节点包含了键值和数据,非叶子节点只是包含键值和子节点引用,不包含数据。
通过非叶子节点查询叶子节点获取相应的数据,所有相邻的叶子节点包含非叶子节点使用链表进行结合,叶子节点是顺序并且相邻节点有顺序引用关系。
B和B+树的区别
innodb存储引擎是用b+树实现的索引结构
它们的不同之处是 b+的非叶子节点只存键值对信息,且所有叶子节点都有双向链表指针,可以基于叶子节点范围查找,或者基于根节点查找,而数据索引都存放在叶子节点中
回顾mybatis第一天
我其实有个自己的笔记的,而且代码也完成过了,所以尽可能记录一些我想写的,毕竟之前记录的总不能再费时间去重写一遍,肯定是按着之前的笔记记录一个简单的步骤,不再那么详细了,尽可能用文字简化(相当于精简成属于自己的目录,内容就不写了)
另外我感觉mybatis-plus也挺好的啊,就是不知道为什么跟docker一样骂声这么多,应该是我还没去公司上手业务,在学习阶段感觉不出来,太遗憾了。
通用pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu.mybatis</groupId>
<artifactId>mybatis_helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!-- Mybatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<!-- log4j日志 -->
<!-- log4j.xml放在resources里面 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>
好朴素的pom少了springboot的那些依赖
后面的用springboot就直接全局配置了,学的mybatis还是用的javaweb那一套,需要写config,这里的config不是写在java里,是写在resources 包括mappers的映射路径也是一样的,都写在config.xml,所以就不记录了,真用到了去官网找xml粘得了
经典的java mapper对应resources mapper 没有注解,只看一些名词解释
mapper接口和映射文件要保证两个一致: 1、mapper接口的全类名和映射文件的namespace一致 2、mapper接口中的方法的方法名要和映射文件中的sql的id保持一致
resultType:设置结果类型,即查询的数据要转换为的java类型//同名 resultMap:自定义映射,处理多对一或一对多的映射关系//就是别名 二选一
跟springboot不一样的,很多东西都要写在mybatis-config里面,这部分看plus就行了 真要用去官网看一下就行
贴一下我自己原来的笔记
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
MyBatis核心配置文件中的标签必须要按照指定的顺序配置:
properties?,settings?,typeAliases?,typeHandlers?,
objectFactory?,objectWrapperFactory?,reflectorFactory?,
plugins?,environments?,databaseIdProvider?,mappers?
-->
<!--引入properties文件,此后就可以在当前文件中使用${key}的方式访问value-->
<properties resource="jdbc.properties" />
<!--
typeAliases:设置类型别名,即为某个具体的类型设置一个别名
在MyBatis的范围中,就可以使用别名表示一个具体的类型
-->
<typeAliases>
<!--
type:设置需要起别名的类型 类型别名
alias:设置某个类型的别名
-->
<!--<typeAlias type="com.atguigu.mybatis.pojo.User" alias="abc">
别名是abc </typeAlias>-->
<!--若不设置alias,当前的类型拥有默认的别名,即类名且不区分大小写-->
<!--<typeAlias type="com.atguigu.mybatis.pojo.User">
别名是User </typeAlias>-->
<!--通过包设置类型别名,指定包下所有的类型将 全部拥有默认的别名!!
,即类名且不区分大小写-->
<package name="com.atguigu.mybatis.pojo"/>
</typeAliases>
<!--
environments:配置连接数据库的环境
属性:
default:设置默认使用的环境的id
//默认使用下面环境 development
//没有引用test
-->
<environments default="development">
<!--
environment:设置一个具体的连接数据库的环境
属性:
id:设置环境的唯一标识,不能重复
-->
<environment id="development">
<!--
transactionManager:设置事务管理器
属性:
type:设置事务管理的方式
type="JDBC|MANAGED"
JDBC:表示使用JDBC中原生的事务管理方式
MANAGED:被管理,例如Spring
-->
<transactionManager type="JDBC"/>
<!--
dataSource:设置数据源
属性:
type:设置数据源的类型
type="POOLED|UNPOOLED|JNDI"
POOLED:表示使用数据库连接池
UNPOOLED:表示不使用数据库连接池
JNDI:表示使用上下文中的数据源
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--引入mybatis的映射文件-->
<mappers>
<!--<mapper resource="mappers/UserMapper.xml"/>-->
<!--
以包的方式引入映射文件,但是必须满足两个条件:
1、mapper接口和映射文件所在的包必须一致
com.atguigu.mybatis.mapper
看着位置不一样 在target里面加载在同一个目录下
2、mapper接口的名字和映射文件的名字必须一致
UserMapper UserMapper.xml
-->
<package name="com.atguigu.mybatis.mapper"/>
</mappers>
</configuration>
properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
jdbc.username=root
jdbc.password=123456
总结
这几天有点事,每天早上电话没断过,也不知道论文抽检还要不要去线下对峙,反正纸质材料得交上去,而且少不了跟指导老师1V1对线,抓紧检查完得了,天天压在心里面,本来感觉最近想法很多,心挺乱的,还整个20选2中奖,麻了,前天的也没发上去,麻上加麻。
另外,感觉看了plus再看mybatis后感觉没plus用的方便,目前看了三分之一了,两天应该能结束,前面都在讲怎么配置,刚看到传参,估计明天能看见一些经典回顾知识点。