「这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战」。
导读
在刚刚结束的 每日算法&面试题,大厂特训二十八天 和 冲刺大厂每日算法&面试题,动态规划21天 的训练中我们一起打卡走了过来。但是学习不能停呀,从今天开始我们开始Java集训(算法&&面试题)第一天接着卷起来。
Java集训
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
思路:链表的缺点在于不能通过下标访问对应的元素。因此我们可以考虑对链表进行遍历,同时将遍历到的元素依次放入数组 A 中。如果我们遍历到了 N 个元素,那么链表以及数组的长度也为 N,对应的中间节点即为 A[N/2]。
初始化:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
解题部分:
class Solution {
public ListNode middleNode(ListNode head) {
ListNode[] A = new ListNode[100];
int t = 0;
while (head != null) {
A[t++] = head;
head = head.next;
}
return A[t / 2];
}
}
给定二叉树的根节点 root ,返回所有左叶子之和。
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:
输入: root = [1]
输出: 0
初始部分:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
解题部分:
深度优先搜索
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
return root != null ? dfs(root) : 0;
}
public int dfs(TreeNode node) {
int ans = 0;
if (node.left != null) {
ans += isLeafNode(node.left) ? node.left.val : dfs(node.left);
}
if (node.right != null && !isLeafNode(node.right)) {
ans += dfs(node.right);
}
return ans;
}
public boolean isLeafNode(TreeNode node) {
return node.left == null && node.right == null;
}
}
面试题
自己写过 String 类能加载吗,之前的 String 是什么时候加载进去的?
不能加载,因为双亲委派机制,JVM 出于安全性的考虑,全限定类名相同的 String 是不能
被加载的。
java.lang.String 会被顶级类加载器 Bootstrap Classloader 加载。当 class 文件被加载到
内存中时,类文件常量池中的其他常量会加载到运行时常量池,但是字符串常量不会。它会首
先在堆区中创建一个字符串对象,然后再把这个对象的引用保存到全局字符串常量池中。
、描述 ThreadLocal(线程本地变量)的底层实现原理及常用场景?
实现原理:
每个 Thread 线程内部都有一个 ThreadLocalMap;以线程作为 key,泛型作为 value,
可以理解为线程级别的缓存。每一个线程都会获得一个单独的 map。
提供了 set 和 get 等访问方法,这些方法为每个使用该变量的线程都存有一份独立的副
本,因此 get 方法总是返回由当前执行线程在调用 set 时设置的最新值。
应用场景:
JDBC 连接
Session 管理
Spring 事务管理
调用链,参数传递
AOP
ThreadLocal 是一个解决线程并发问题的一个类,用于创建线程的本地变量,我们知道一个
对象的所有线程会共享它的全局变量,所以这些变量不是线程安全的,我们可以使用同步技术。
但是当我们不想使用同步的时候,我们可以选择 ThreadLocal 变量。例如,由于 JDBC 的
连接对象不是线程安全的,因此,当多线程应用程序在没有协同的情况下,使用全局变量时,
就不是线程安全的。通过将 JDBC 的连接对象保存到 ThreadLocal 中,每个线程都会拥有
属于自己的连接对象副本