- 博客(42)
- 收藏
- 关注
原创 双非本科准备秋招(23.1)—— 力扣二叉搜索树
根据二叉搜索树的特点,使用前序遍历,只要当前节点的值在p、q之间,就代表当前节点是二叉搜索树的最近公共祖先。:每次更新最大值的时候,顺便清空数组,这样最后数组里一定都是最高频次的元素了。中序遍历得到有序数组和最高频次,然后再次遍历有序数组。核心思想就是层层返回拥有p或者q的节点。
2024-02-13 10:33:24
276
原创 双非本科准备秋招(22.2)—— 多线程交替打印
我们建一个类,能实现交替打印,比如打印abcabcabc,并且能控制打印次数。让类继承ReentrantLock。类中有一个控制循环的变量。建立三个线程,第一个线程当前条件变量为a,然后唤醒b,依次进行。,提供一个print方法,接收3个参数,一个是待打印的值。主线程:打印3次,新建三个条件变量,分别是a、b、c。一开始,三个线程启动,然后各自进入等待状态,了a条件变量,然后开始依次打印abc。,一个是要唤醒的下一个条件变量。,一个是当前条件变量。
2024-02-10 16:27:48
308
原创 双非本科准备秋招(22.1)—— 力扣二叉搜索树
改造一下前序遍历,最后一个参数sum就是和,判断node.val的值是否在范围内,如果在范围内,那么就累加到sum中,然后再让sum加上左右子树的sum值即可。然后,将值跟parent的左右子树的val作比较,小于就加在parent左边,大于就加在parent右边。TreeNode为pre,默认是null,每次操作完之后,都重新记录一下pre的值,这样我们就能得到之前和现在的节点了。中序遍历的非递归实现,我们中序遍历二叉搜索树,得到的结果一定是递增的,否则就不是二叉搜索树。
2024-02-10 16:27:44
548
原创 双非本科准备秋招(21.2)—— ReentrantLock
wait和notify的模板语法中,每次都要notifyAll,然后所有的wait线程都被唤醒,如果条件没满足,就是虚假唤醒。创建一个条件变量,这个案例中模拟两个线程,一个线程需要吃苹果才能工作,一个线程需要卫生纸才能工作。但是使用了多个条件变量,我们就不需要盲目地唤醒所有线程了。方法,尝试获得锁,如果能获得锁就获得,返回true,否则返回false。方法,可以让当前线程进入等待。可以加一个boolean参数,true代表公平锁,默认是不公平的。还需要一个唤醒线程,这里就可以看出来条件变量的优势,
2024-02-09 11:46:24
521
原创 双非本科准备秋招(20.2)—— 线程活跃性:死锁、活锁、饥饿
需要获得,就容易出现死锁。比如此时有两把锁,分别是A和B。首先需要获得A,然后获得B;首先需要获得B,然后获得A。于是两个线程就一直等待对方释放锁。
2024-02-08 23:39:45
679
原创 双非本科准备秋招(20.1)—— 并发编程之生产者消费者
方法:检查list是否满了,满了的话就wait,如果不满就添加Message,并唤醒所有线程。方法:检查list是否是空,空的话就wait,如果不空就打印Message,并唤醒所有线程。可以看到,以上的写法都是使用wait和notify的模板写法。类,需要一个唯一标识id,还需要一个Object类型的value值。结果数据,不关心数据该如何处理,而消费者专心。首先,设计消息队列类。产生结果和消费结果的线程。与保护性暂停中的不同,,采用的就是这种模式。
2024-02-08 09:33:46
233
原创 双非本科准备秋招(19.1)—— Synchronized优化
一个对象虽然有多线程加锁,但是加锁时间是的,那么可以用轻量级锁优化。语法还是synchronized,只是对使用者是透明的。首先,会先创建锁记录(Lock Record)对象,每个线程的都会包含一个锁记录的结构,内部可以存储锁定。然后,让锁记录中指向,并尝试用 cas 替换 Object 的 Mark Word,将 Mark Word 的值存 入锁记录替换分为成功和失败:替换锁记录中存储了对象的MarkWord,00代表轻量级锁,01代表无锁。替换当。
2024-02-07 19:21:11
1114
原创 双非本科准备秋招(18.2)—— 图解Monitor
java中对象存储结构分为(Header)、(Instance Date)和(Padding)。对象头存储着Mark Word和Klass Word,通过Klass Word,程序才知道这个对象是一个什么对象。Mark Word占32位。结构如下,有五种不同的类型,重点记一下:01偏向锁、00轻量级锁、10重量级锁。
2024-02-06 22:10:16
889
原创 双非本科准备秋招(17.2)—— 线程八锁
一段代码块内存在对的多线程读写操作,这段代码就是临界区。:多个线程在临界区执行,由于代码不同导致结果无法预测,称发生了竟态条件。为了避免的此次使用阻塞式解决方案:synchronized,俗称,这样,同一时刻只能有一个线程能持有对象锁,其他线程想获得这个对象锁就会被阻塞。
2024-02-05 23:13:47
449
原创 双非本科准备秋招(17.1)—— 力扣二叉树
观察以上内容,我们可以这样做:找到前序遍历的节点,然后循环遍历中序数组,找到第i个元素是根节点,这时候继续递归寻找左子树,左子树的前序数组下标为1~i,中序数组为0~i-1;每次递归前,都让字符串s加上当前节点的值和“->”,然后判断是否为叶子节点,如果是的话,说明这条路径是一个答案,因为最后多一个->,所以用substring去掉。同样的,我们遍历左子树4 2,在前序中找到根,得到根是2,于是开始循环······首先,要确认根节点的值,根节点就是前序遍历的第一个节点。的顺序,所以根的左右两侧就是左子树。
2024-02-05 18:24:32
802
原创 双非本科准备秋招(16.1)—— 力扣二叉树
这个解法实际上就是改造一下非递归后序遍历的代码,因为每次遍历都会将节点入栈,我们只需要在弹栈之前,记录一下栈的大小,取最大值就好。最大深度也可以用层序遍历来写,因为层序遍历就是遍历每一层嘛,最大深度就遍历到最后一层,最小深度就遍历到第一个叶子节点就好了。如果两个值相等,不代表一定对称,还需要继续检查左节点的左节点和右节点的右节点、左节点的右节点和右节点的左节点是否相等。要求这棵树的最大深度,我们只需要求左子树和右子树的深度,然后取最大值加一就好,同样地对每个节点都如此,于是就可以用递归来解。
2024-02-04 23:17:23
1160
原创 双非本科准备秋招(15.3)—— 力扣二叉树
今天学了二叉树结点表示法,建树代码如下。我们建一棵树,然后使用递归的方式前中后序遍历(preOrder、inOrder、postOrder),再使用非递归方式遍历(traversal)。
2024-02-03 21:06:09
561
原创 双非本科准备秋招(15.2)—— java线程常见方法
也就是说,调用了yield会让线程进入Runnable状态,但有可能还会继续给这个线程分配时间片,导致没有将cpu资源让出去,但是sleep会真正让出cpu资源,cpu调度时不会考虑sleep的线程。线程优先级会提示调度器优先调度该进程,但是调度器可以忽略它,cpu忙的时候,优先级高的获得的时间片多,但是cpu闲的时候,优先级几乎没用。2、打断正常线程,并不会真的打断,只是添加打断标记,正常线程可以通过检查自己的打断标记来查看是否被打断。run还是让主线程操作,start可以让线程就绪。
2024-02-03 09:33:52
1341
原创 双非本科准备秋招(14.3)—— java线程
学完JVM之后就很清楚了,每个线程的创建都会伴随一个虚拟机栈的创建,线程中的一个个方法就是一个个栈帧,每次运行一个方法就会进入虚拟机栈,方法结束后会出栈。举例:通过setDaemon(true)可以设置线程为守护线程,可以看到守护线程中的“运行结束”根本没打印出来,就被停止了。默认情况下,java进程会等待所有线程结束,才会结束。但是守护线程特殊,只要其他非守护线程结束了,那么就会。上下文切换时,需要保存当前线程的状态,jvm的每个线程都有自己的程序计数器(PCR),用来记录下一条jvm指令的地址。
2024-02-02 23:20:04
744
原创 双非本科准备秋招(14.2)—— 进程与线程
但如果是单核cpu,串行用时10+11+12 = 33ms,如果这时开三个线程,时间肯定大于33ms,因为cpu是单核的,实际上还是在串行执行这些线程,还需要上下文切换的时间,更加耗时。例如项目中的视频文件格式转换,需要耗费大量时间,这时候就需要新开一个线程处理视频文件格式转换,避免阻塞了主线程。进程也可以看作一个程序的实例,大部分程序可以运行多个实例进程,比如记事本,有的程序只能启动一个实例进程,如果qq音乐。线程可以理解为一个进程的执行实体,多个线程组成一个进程,是操作系统。多线程可以让方法变成异步。
2024-02-02 22:31:09
442
原创 双非本科准备秋招(13.1)—— 力扣 栈、队列与堆
我们把a入栈,b入栈,b入栈,b和栈顶重复,b不入了并且弹出栈顶元素,这时候栈只剩下a,然后a入栈,a和栈顶重复,a不入了并且弹出栈顶元素,栈空了,然后c入栈,a入栈。前k个高频元素,有出现了前几个具有xx特性的这种要求,我们就会想到堆,在堆中只存放前k个高频元素,使用小顶堆,我们最后得到的就是前k个最高频的元素了。因为堆中第一个元素是k个中最小的,我们不断加入大的元素,那么最后是不是堆中只剩下最大的k个元素了,k个最大元素中最小的不就是堆的第一个元素嘛。元素与元素的次数,让人联想到哈希表。
2024-02-01 23:00:16
750
原创 双非本科准备秋招(12.1)—— JVM4:类文件结构与加载机制
恢复元气,最后一天学JVM!学了五天JVM了,不打算学的太深,这几天收获也很多,对很多底层原理有了那么一点了解,以后肯定还会继续加深JVM的学习理解的,暂时先到此为止,接下来是为期一个星期的JUC并发编程学习。
2024-01-31 19:10:21
1248
原创 双非本科准备秋招(11.1)—— 重学泛型
Java泛型(Generics),JDK5引入的新特性。泛型参数能增强代码的可读性和稳定性。编译器可以对泛型参数进行检测,通过泛型参数可以指定传入对象的类型,比如ArrayList<People> list = new ArrayList<>();指定只能传入People对象,否则报错。
2024-01-30 11:07:02
294
1
原创 双非本科准备秋招(10.2)—— JVM3:垃圾收集器
的阶段,因为是并发的,用户此时可能还会产生新的垃圾,所以会留出一部分预留内存存放浮动垃圾,如果这块内存不足,会出现Concurrent Mode Failure错误,这时,虚拟机会启用Serial Old替代CMS。统计各个Region的回收价值和成本并排序,根据用户期望的停顿时间制定回收计划,筛选任意多个Region构成回收集,然后将回收部分的存活对象复制到空Region中,再清理整个旧Region空间。进行GC Roots Tracing的过程,不需要STW,与用户进程并发执行,时间最长。
2024-01-29 22:55:28
2699
原创 双非本科准备秋招(10.1)—— 力扣刷题
三数之和是判断和是否为0,这个题是判断和是否为target,那么就不能简单地认为nums[i]>0就break了。那么需要反转的位置就是从i到i+k,也就是[i, i+k),那么如果不足呢,如果长度不足加k,那么就反转从i到总长度的位置就行,要是不足2k不用处理,因为会默认处理i到i+k,剩下的部分不会进入循环。然后j是end-(i-begin)-1,i-begin的取值会是0,1,···,所以j会不断缩小。分两步处理,先想想怎么获取需要反转的字符串,再想想反转字符串需要怎么做。剩下的就没啥区别了。
2024-01-29 15:24:22
419
原创 双非本科准备秋招(9.3)—— JVM2
学这个JVM还是挺抽象的,不理解的东西我尽量记忆了,毕竟刚接触两天,也没遇到过实际应用场景,所以学起来还是挺费劲的,明天再补完垃圾回收这块的知识点。U•ェ•*U。
2024-01-28 22:37:23
1096
1
原创 双非本科准备秋招(9.2)——力扣哈希
这样就拆成两个哈希表了,遍历一个哈希表,那么-key就是另一个哈希表中需要存在的值,如果存在,这两个哈希表的value之积就是一个解。因为是排完序的,那么我只需要保证i和上一个元素不相等即可,如下图,如果i和上一个元素相等,说明接下来得到的值肯定都是重复的。对每个-1来说,都能找到3个1。然后是对nums[j]和nums[k]去重,比如这种的,会找到两组(-1, 0, 1)。然后遍历数组,i就是遍历的元素,j和k是双指针,通过移动j和k来取得答案。开始上强度了,200个数据,直接暴力,200的4次方不行。
2024-01-28 22:37:02
523
原创 双非本科准备秋招(9.1)——重学排序与自定义比较
一种是Arrays的sort()方法,可根据各种数据类型(基本与引用类型)数组排序。一种是Collections的sort(),针对集合进行排序(例如ArrayList、TreeMap等)但是如果我们想要自定义排序规则时,就需要用到两个接口。Comparable接口,出自java.lang,需要重写compareTo(Object obj)方法Comparator接口,出自java.util,需要重写compare(Object obj1, Object obj2)方法先分别介绍一下,再进行比较。
2024-01-28 10:50:58
370
原创 双非本科准备秋招(8.2)——JVM1
第一天系统学习JVM!今天学了JVM是什么,学习JVM的作用,运行时的数据区域(重点),内存溢出。明天学GC。
2024-01-27 22:55:29
2637
1
原创 双非本科准备秋招(8.3)——重学String
文档的意思大概是,如果常量池已经有了这个字符串对象的引用,那么直接返回这个字符串(string from the pool),要是没有,那么久在常量池添加一个,然后返回这个字符串对象的引用。首先先在堆中创建一个String对象,然后判断字符串常量池是否保存了对应字符串的引用,没有保存,在堆中创建对应的字符串对象(第2个对象)并且将字符串对象的引用保存到字符串常量池中。JVM为了提升性能和减少内存消耗,针对字符串专门开辟的区域,避免字符串重复创建,这里存放的是字符串对象的引用。
2024-01-27 14:35:17
875
1
原创 双非本科准备秋招(8.1)——力扣哈希
学到的知识:1、String的toCharArray()方法能返回一个Char类型的数组,自己发现对String学的还不系统,于是重新学了下String。2、new ArrayList()可以接收一个Collection对象3、map的keySet和values方法,分别返回Set和Collection类型的对象。分析:字母异位词是乱序的,也就是说,如果排序的话,那么异位词就相等了,比如"ab"、"ba",排序之后都是"ab"。
2024-01-27 14:31:10
659
1
原创 双非本科准备秋招(7)——力扣哈希、二分与容器学习
学了三天容器的知识了,追踪了不少次源码,整体上有所感悟,今天再背背容器的相关面试题啥的就结束了,明天开始学JVM。
2024-01-26 18:24:24
2264
1
原创 双非本科准备秋招(6)—— Collection、Map学习与源码追踪2
大概就理解这些吧,看源码太耗功力了,源码这东西,看起来费劲,写起来更费劲,不如自己多追踪追踪体会体会。本来还想写写LinkedHashMap、HashSet、LinkedHashSet的,不写了不写了。HashSet底层就是HashMap,底层传入的Value是一个默认值,而LinkedHashSet底层是LinkedHashMap,而LinkedHashMap的底层还是HashMap,其实还是HashMap的那些核心源码,只是维护了一个双向链表来实现取元素有序。
2024-01-25 22:10:59
681
原创 双非本科准备秋招(5)——力扣回溯法解决链表问题、Collection接口的实现类与源码追踪1
每天记录博客让我有动力保持学习状态,每天不学点东西写写博客都对不起自己,学的时候不认真都不好意思写下来,把每天学的东西再清晰地表达一遍对我来说还是蛮困难和耗时间的,但写完之后感觉自己的思路也清晰了很多,好多有遗忘的知识点又重新想起来了,果然,输出是最好的学习方式。
2024-01-24 23:23:43
1042
原创 双非本科准备秋招(4)——力扣链表与java基础
java操作链表的时候要比c++方便一些,因为c++需要自己手动释放资源,而jvm虚拟机具有垃圾回收机制(GC),如果这个对象将来没被引用过,就会自动回收其所占用的内存。LeetCode上的链表结构不是定义的集合形式,而是结点形式,什么意思呢,举个例子。这种就属于集合的方式定义链表,在里面定义内部类Node节点对象,如果需要使用,只需要创建链表对象,调用其中的方法。LeetCode上的相当于把Node节点类直接拿出来,用头节点代表整个链表。
2024-01-23 21:13:42
1050
1
原创 双非本科准备秋招(3)——力扣数组
审题很关键啊,读不懂题目或者一知半解都不要敲代码,思路比代码更重要,好好读读题意思也挺明显,让你返回一个len,代表移除完毕后的数组长度,要求数组下标为0到len-1的元素都是没删除的元素。一开始思路也不是很清晰,感觉应该有比较巧妙的方法,最后也没想出来,弄了个新数组记录一下原数组保留的元素,然后copy到原数组,过了。参数:original:要拷贝的数组对象from:为拷贝的开始位置(包含)to:拷贝的结束位置(不包含)
2024-01-22 21:42:00
728
1
原创 双非本科准备秋招(2)——力扣基础sql与二分搜索
备战秋招第二天,leetcode刷刷简单的sql查询和二分搜索算法,收获颇丰,刷题还是得亲手做,避免眼高手低。
2024-01-21 23:16:20
911
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人