LeetCode-08/08/2022
This is a record of my craking process for Leetcode.
Word Break ()#
1 | class Solution { |
Unique Binary Search Trees II()#
1 | /** |
Number of Music Playlists()#
1 | class Solution { |
Search in a 2D matrix()#
1 | class Solution { |
This is a record of my craking process for Leetcode.
1 | class Solution { |
1 | /** |
1 | class Solution { |
1 | class Solution { |
This is a record of my craking process for Leetcode.
Considering the base case (1 * 3) There are several possible choices. 121 212 213 232 312 313 (1 2 3 represents RGB 3 different colors). Then we can consider the next following posible choice in (2 * 3)
Let 121 represents head and tail have the same color and the middle pos varies
Let 123 represent every pos has different color
Then we can derive the following fomular
$$b_{121} = a_{121} * 3 + a_{123} * 2$$
$$b_{123} = a_{121} * 2 + a_{123} * 2$$
1 | class Solution { |
1 | impl Solution { |
The trick in this problem is to consider the impossible cases (The robot does not come back to original nor the bot face the initial position after iteration)
1 | class Solution { |
1 | impl Solution { |
This is a record of my craking process for Leetcode.
The most simple way is two use brute-force (which takes $n^2$ time) But we can optimize it with binary-search
1 | class Solution { |
1 | use std::cmp; |
An alternate way is doing one loop (going thorugh the two-dimension table) starting from right-top corner.
When we reach a ‘1’ we choose to go left otherwise go down
1 | class Solution { |
1 | use std::cmp; |
A very straight-forward 2-point method
1 | class Solution { |
1 | impl Solution { |
This is a record of my craking process for Leetcode.
You are given a list of songs where the ith song has a duration of time[i] seconds.
Return the number of pairs of songs for which their total duration in seconds is divisible by 60. Formally, we want the number of indices i, j such that i < j with (time[i] + time[j]) % 60 == 0.
Example 1:
Input: time = [30,20,150,100,40]
Output: 3
Explanation: Three pairs have a total duration divisible by 60:
(time[0] = 30, time[2] = 150): total duration 180
(time[1] = 20, time[3] = 100): total duration 120
(time[1] = 20, time[4] = 40): total duration 60
Example 2:
Input: time = [60,60,60]
Output: 3
Explanation: All three pairs have a total duration of 120, which is divisible by 60.
The most straight-forward way to solve this problem is using two loops which takes $n^2$ time. To optimize it, we can use the same way with two sum, but do a small modification. Since we only need to output the pairs, we use an array (size of 60) to record the current value % 60. Then while in the for-loop, we can check 60 - current_value % 60, get its occurences.
1 | class Solution { |
1 | impl Solution { |
Here is my personal notes for Rust
one memory block can only have one mutable ref but it can have multiple immutable ref. Also, once a memory block has one mutable ref, all the immutable refs before that would be invalid.
For my understanding:
Mutable ref is like a “read and write” operation to memory block, while immutable ref is like a “read only” operation to the memory block. Once you have a “read and write” operation(mutable ref), all other “read only” operation(mutable ref) don’t know what happened to that memory block(might be changed by mutable block), so, the result from “read only” operation may not be valid. However, we have to re-create mutable refs.~
Java编译器输入的指令流基本上是一种基于栈的指令集架构,另外一种指令集架构则是基于寄存器的指令集架构。具体来说:这两种架构之间的区别:
1 | javap -v StackStruTest.class |
1 | public static void main(java.lang.String[]); |
Java虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实现指定的
完整框图
类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。
ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。
加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)
class –> Java.lang.Class
class file存在于本地硬盘上,可以理解为设计师画在纸上的模板,而最终这个模板在执行的时候是要加载到JVM当中来根据这个文件实例化出n个一模一样的实例。
class file加载到JVM中,被称为DNA元数据模板,放在方法区。
在.class文件–>JVM–>最终成为元数据模板,此过程就要一个运输工具(类装载器Class Loader),扮演一个快递员的角色。
1 | public class HelloLoader { |
类的加载过程
执行 main() 方法(静态方法)就需要先加载承载类 HelloLoader
加载成功,则进行链接、初始化等操作,完成后调用 HelloLoader 类中的静态方法 main
加载失败则抛出异常
完整的流程图如下所示:加载 –> 链接(验证 –> 准备 –> 解析) –> 初始化
链接分为三个子阶段:验证 –> 准备 –> 解析
验证
举例
使用 BinaryViewer 查看字节码文件,其开头均为 CAFE BABE ,如果出现不合法的字节码文件,那么将会验证不通过
准备
举例
1 | public class HelloApp { |
解析(Resolve)
解析
<clinit>()
的过程<clinit>()
方法中的指令按语句在源文件中出现的顺序执行<clinit>()
不同于类的构造器。(关联:构造器是虚拟机视角下的<init>()
)<clinit>()
执行前,父类的<clinit>()
已经执行完毕<clinit>()
方法在多线程下被同步加锁1 | public class ClassInitTest { |
静态变量 number 的值变化过程如下
1 | blic class ClassInitTest { |
静态变量 number 的值变化过程如下
1 | public class ClinitTest { |
1 | public class ClinitTest1 { |
如上代码,加载流程如下:
1 | public class DeadThreadTest { |
程序卡死,分析原因:
类加载器的分类
ExtClassLoader 继承树
代码:
1 | public class ClassLoaderTest { |
启动类加载器(引导类加载器,Bootstrap ClassLoader)
扩展类加载器(Extension ClassLoader)
应用程序类加载器(系统类加载器,AppClassLoader)
1 | public class ClassLoaderTest1 { |
1 | **********启动类加载器************** |
为什么需要自定义类加载器?
在Java的日常应用程序开发中,类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方式。那为什么还需要自定义类加载器?
如何自定义类加载器?
1 | public class CustomClassLoader extends ClassLoader { |
ClassLoader 类介绍
ClassLoader类,它是一个抽象类,其后所有的类加载器都继承自ClassLoader(不包括启动类加载器)
sun.misc.Launcher 它是一个java虚拟机的入口应用
获取class的途径
1 | public class ClassLoaderTest2 { |
双亲委派机制的原理
Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式
如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行;
如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器;
如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。
父类加载器一层一层往下分配任务,如果子类加载器能加载,则加载此类,如果将加载任务分配至系统类加载器也无法加载此类,则抛出异常
Example1
1 | package java.lang; |
1 | public class StringTest { |
Example2
1 | package java.lang; |
当我们加载jdbc.jar 用于实现数据库连接的时候
首先我们需要知道的是 jdbc.jar是基于SPI接口进行实现的
所以在加载的时候,会进行双亲委派,最终从根加载器中加载 SPI核心类,然后再加载SPI接口类
接着在进行反向委托,通过线程上下文类加载器进行实现类 jdbc.jar的加载。
双亲委派机制的优势
通过上面的例子,我们可以知道,双亲机制可以
Example:在 java.lang 包下整个 ShkStart 类
1 | package java.lang; |
出于保护机制,java.lang 包下不允许我们自定义类
自定义String类时:在加载自定义String类的时候会率先使用引导类加载器加载,而引导类加载器在加载的过程中会先加载jdk自带的文件(rt.jar包中java.lang.String.class),报错信息说没有main方法,就是因为加载的是rt.jar包中的String类。这样可以保证对java核心源代码的保护,这就是沙箱安全机制。
如何判断两个class对象是否相同?
在JVM中表示两个class对象是否为同一个类存在两个必要条件:
对类加载器的引用
类的主动使用和被动使用
Java程序对类的使用方式分为:主动使用和被动使用。主动使用,又分为七种情况:
除了以上七种情况,其他使用Java类的方式都被看作是对类的被动使用,都不会导致类的初始化,即不会执行初始化阶段(不会调用 clinit() 方法和 init() 方法)
string.trim() is used to trim leading and tailing spaces in a String
If we want to split a string by multiple spaces we can use string.split(“\\s+”)
If we want to concatenate a list of string, we can use String.join(“ “, wordList).
Lambda expression used in sorting List or Array
1 | arr1.sort((a, b) -> Integer.compare(a[1] - a[0], b[1] - b[0])); |
配置类 == 配置文件
1 | //配置类 |
MyTypeFilter.java 自定义Filter的实现类
1 | public class MyTypeFilter implements TypeFilter{ |
使用@Scope调整作用域
1 | @Configuration |
Color
1 | //随便创一个,假装外部组件 |
MyImportSelector.java
1 | //自定义逻辑 返回需要导入的组件 |
LinuxCondition.java
1 | //判断是否是linux系统 |
MyImportBeanDefinitionRegistrar.java –> 手工注册
1 | public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{ |
ColorFactoryBean
1 | //创建一个spring定义的FactoryBean |
WindowsCondition
1 | //判断是否是windows系统 |
配置文件
1 | <!--配置文件--> |
BookController.java
1 | @Controller |
BookService.java
1 | @Service |
BookDao.java
1 | @Repository |
Main 函数
1 | public class MainTest{ |
IOCTest.java
1 | public class IOCTest{ |
Bean的生命周期
MainConfigOfLifeCycle.java
1 | /* bean的生命周期 |
MyBeanPostProcessor.java
1 | /* |
Car.java
1 | public class Car{ |
Cat.java
1 | @Component |
Dog.java
1 | @Component |
IOCTest_LifeCycle.java
1 | public class IOCTest_LifeCycle{ |
属性赋值
MainConfigOfPropertyValues.java
1 | @Configuration |
Person.java
1 | public class Person{ |
person.properties
1 | person.nickName = xxx |
IOCTest_LifeCycle.java
1 | public class IOCTest_PropertyValue{ |
自动装配
MainConfigAutowired.java
1 | /* |
Boss.java
1 | //默认加载ioc容器中的组件 容器启动会调用无参构造器创建对象,再进行初始化赋值等操作 |
IOCTest_Autowired.java
1 | public class IOCTest_Autowired{ |
Profile
1 | /* |
dbconfig.proerties
1 | db.user = root |
MainConfigOfAOP.java
1 | /* |
MathCalculator
1 | public class MathCalculator{ |
LogAspects.java
1 | //告诉spring当前类是切面类 |
This is a personal notes for Java spring framework
It is a very popular framework for building Java application and initially a simpler and light weight alternative to J2EE. Also, it provides a large number of helper classes.
Factory for creating beans. Manage bean dependencies.
Aspect Oriented Programming. Add functionality to objects declaratively.
Logging, security,transactions,etc…
All Web related classes. Home of the Spring MVC framework.
Supports Test-Driven-Development(TDD). Mock objects and out-of-container testing
The dependency inversion principle.
The client delegates to calls to another object
the responsibility of providign its dependencies
suppose function A() is marked as async, if we want to call A in function B, usually we use await and marked b as async. However, if we dont want to modify the return type of B. To solve that, I decide to use anonymous function to encapsulate the calling of function A, then receive the return_val of A sync.
1 | public int B(){ |
AutoMapper is an object-object mapper. Object-object mapping works by transforming an input object of one type into an output object of a different type. What makes AutoMapper interesting is that it provides some interesting conventions to take the dirty work out of figuring out how to map type A to type B. As long as type B follows AutoMapper’s established convention, almost zero configuration is needed to map two types.
Once you have your types you can create a map for the two types using a MapperConfiguration and CreateMap. You only need one MapperConfiguration instance typically per AppDomain and should be instantiated during startup. More examples of initial setup see in Setup.
1 | var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>()); |
The type on the left is the source type, and the type on the right is the destination type. To perform a mapping, call one of the Map overloads:
1 | var mapper = config.CreateMapper(); |
1 | var obj2 = Mapper.Map<Obj1, Obj2>(obj1); |