美菜网
Java类定义如下,写出main函数执行后输出的结果
public class A {
static {
System.out.println("static A");
}
public A() {
System.out.println("class A");
}
}
public class B extends A{
public B() {
System.out.println("class B");
}
public static void main(String[] args) {
B instance = new B();
}
}
简单的类加载顺序,口诀如下
执行顺序
- 父类的静态(静态代码块,静态成员变量),子类的静态(静态代码块,静态成员变量)
- 父类的非静态(构造代码块,非静态成员变量),父类的构造函数
- 子类的非静态(构造代码块,非静态成员变量),子类的构造函数
所以输出输出如下;
static A
class A
class B
面试官还问了一个问题如果main函数中的代码如下呢?就是B这个类new2次
public static void main(String[] args) {
B instance = new B();
B instance1 = new B();
}
输出应该如下
static A
class A
class B
class A
class B
因为静态成员变量和静态代码块只会在类被载入内存时加载一次
写出main函数执行后输出的结果
public class T extends Thread {
public T() {
this.setName("Thread t");
this.printName();
}
public void run() {
this.printName();
}
private void printName() {
String name = Thread.currentThread().getName();
System.out.println(name);
}
public static void main(String[] args) {
Thread.currentThread().setName("Thread main");
T t = new T();
t.start();
}
}
输出如下:
Thread main
Thread t
解释如下:
new T()的时候,因为此时在主线程,线程名字为main,
t.start()后,此时在t线程,线程名字为t
链表反转(这个大厂超级爱问)
Leetcode原题
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode cur = head.next;
head.next = null;
ListNode temp;
while (cur != null) {
temp = cur.next;
cur.next = head;
head = cur;
cur = temp;
}
return head;
}
}
多线程安全的单例类
单例有5种写法,具体看Java识堂微信公众号,不再阐述,一般人写双重检测锁定,我建议写静态内部类的实现方式,看起来比较优雅
public class Singleton {
private static class SingletonHolder {
private static Singleton uniqueInstance = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return SingletonHolder.uniqueInstance;
}
}
饿汉式的方式只要Singleton类被装载了,那么uniqueInstance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,uniqueInstance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化uniqueInstance
Linux中根目录包含哪些目录?功能是什么?
Linux中通过命令行完成
1.查看磁盘剩余空间
df -h (-h是以人类易读的方式显示出来,如1K 234M 2G)
2.在/tmp目录下查找所有内容包含abc的文件
find /tmp -type f | xargs grep -l 'abc'
Linux下swap分区的作用
在Linux下,SWAP的作用类似Windows系统下的“虚拟内存”。当物理内存不足时,拿出部分硬盘空间当SWAP分区(虚拟成内存)使用,从而解决内存容量不足的情况。
SWAP意思是交换,顾名思义,当某进程向OS请求内存发现不足时,OS会把内存中暂时不用的数据交换出去,放在SWAP分区中,这个过程称为SWAP OUT。当某进程又需要这些数据且OS发现还有空闲物理内存时,又会把SWAP分区中的数据交换回物理内存中,这个过程称为SWAP IN。
当然,swap大小是有上限的,一旦swap使用完,操作系统会触发OOM-Killer机制,把消耗内存最多的进程kill掉以释放内存。
成绩表,学生表,输出每个学生的平均成绩
这个挺简单的,就不再写了
有4个人用一个手电筒,过一座桥洞,每个人过桥洞时间分别为1,2,5,10,桥洞同时只能容纳2个人通过,求所有人通过桥洞的最短时间
去1 2
回1
去5 10
回2
去1 2
总的时间为2 + 1 + 10 + 2 + 2 = 17
有2个列ab,你是建ab索引还是ba索引?
区分度高的列放在前面,假如b列的区分度高,就建ba索引,反之建ab,区分度的相关概念看微信公众号Java识堂中关于建索引的文章
一副扑克牌,除去大小王,随机抽5张,判断这5张是否连续的策略
不除去大小王,大小王可以顶替任意牌,判断这5张是否连续的策略\
最后2道算法题,欢迎大家在下方留言,不再写了
- 类加载顺序
- 输出线程名字
- 反转链表
- 单例模式
- Linux各个文件夹的作用
- /tmp 目录下找含有字符串abc的文件
- linux swap分区的作用
- 成绩表,学生表,输出每个学生的平均成绩
- 有4个人用一个手电筒,过一座桥洞,每个人过桥洞时间分别为1,2,5,10,桥洞同时只能容纳2个人通过,求所有人通过桥洞的最短时间
- 一副扑克牌,除去大小王,随机抽5张,判断这5张是否连续的策略
- 不除去大小王,大小王可以顶替任意牌,判断这5张是否连续的策略
- 索引 ab和ba的区别,区别度不同
- Redis Cluster
考虫网
- 判断2个链表是否相交,注意有环的情况
- 有5000万用户,在一个输入框中输入李,下拉框显示李的可选项,如李1,李2,输入张强,下拉框显示张强的可选项,如张强1,张强2,策略,按姓名分表,或者用es
- 获取一个数组的最大值,最大的2个值,最大的n个值,用快排
还有一个优化思路是比较,n和数组长度的一半的大小,例如100个数求最大的99个,只要求最小的一个就行 - 将n个有序数组组成一个有序数组,归并排序
- dubbo原理
- netty原理
- 给一个数组,元素不重复,求2个数和为6的数组的下标,例如1 2 3 4 5,一种为0 4,一种为1 3,解决方法是把小于6的值放到map中,value为下标,遍历这个map即可
懒投资
打印代码的输出
public class MyTest {
private int a = 1;
private static int b = 1;
private static MyTest myTest = new MyTest();
static {
// 这个是我为了方便理解加的
System.out.println("静态代码块");
b = 200;
}
public MyTest() {
// 这个是我为了方便理解加的
System.out.println("构造函数");
this.a = 10;
this.b = 10;
}
public int sum() {
return this.a + b;
}
public static void main(String[] args) {
// 210
System.out.println(MyTest.myTest.sum());
// 20
System.out.println(new MyTest().sum());
}
}
最终的输出为
构造函数
静态代码块
210
构造函数
20
第二个输出很容易理解,第一个我懂个大概,但没有把握讲清楚,有兴趣的小伙伴可以在下方留言解释一下
一个人上楼梯,每次可以上1阶和2阶,问上到count阶台阶的数量
简单的递推,递归也行,但是感觉没必要,
递推公式为
a[n]=a[n-1]+a[n-2],简单解释一下,数组a[n]表示的是上到n阶台阶的数量,即上到n阶的数量=上到n-1阶的数量+上到n-2阶的数量,这个很容易理解吧,初始变量种类为
a[1]=1,从0阶一步到1阶
a[1]=2,从0阶一步到2阶,从1阶一步到2阶
class Solution {
public int getNum(int num) {
int[] a = new int[num + 10];
a[1] = 1;
a[2] = 2;
for (int i = 3; i <= num; i++) {
a[i] = a[i-1] + a[i-2];
}
return a[num];
}
public static void main(String[] args) {
Solution solution = new Solution();
// 3
System.out.println(solution.getNum(3));
// 5
System.out.println(solution.getNum(4));
}
}
仔细看数量
1 2 3 5 8 13,典型的斐波那契数列啊,所以一个通项公式直接求出第n项
一个人每次上1-n(2<=n<=count)阶台阶,求上到count阶台阶数量
这个是上面题目的变形
递推公式为
a[count]=a[count-1]+a[count-2]+…+a[count-n],简单解释一下,数组a[count]表示的是上到count阶台阶的数量
class Solution {
public int getNum(int n, int count) {
int[] a = new int[count + 10];
a[0] = 1;
a[1] = 1;
a[2] = 2;
for (int i = 3; i <= count; i++) {
for (int j = 1; j <= n; j++) {
a[i] += a[i-j];
}
}
return a[count];
}
public static void main(String[] args) {
Solution solution = new Solution();
// 5
System.out.println(solution.getNum(2, 4));
// 4
System.out.println(solution.getNum(3, 3));
}
}
写一个函数,返回第一个出现的个数为1的字符,如果没有则返回空字符,例如 abbbce返回’a’,aabbcc返回’’,aabce返回b
这个题的思路也挺巧的,我刚开始居然没想出来,后来猛的才意识到,你先别看我写的,先自己想一下
class Solution {
public char getFirstSingleChar(String str) {
Map<Character, Integer> map = new LinkedHashMap();
for (int i = 0; i < str.length(); i++) {
char a = str.charAt(i);
Integer num = map.get(a);
if (num == null) {
map.put(a, 1);
} else {
map.put(a, num + 1);
}
}
for (Map.Entry<Character, Integer> entry: map.entrySet()) {
if (entry.getValue() == 1) {
return entry.getKey();
}
}
return ' ';
}
public static void main(String[] args) {
Solution solution = new Solution();
// a
System.out.println(solution.getFirstSingleChar("abbbce"));
// 空字符
System.out.println(solution.getFirstSingleChar("aabbcc"));
// b
System.out.println(solution.getFirstSingleChar("aabce"));
}
}
这道题用LinkedHashMap解决非常简单,用其他方法解决比较难,如果有更好的方法,欢迎在下方留言
掌上先机
try{}里面有一个return语句,那么紧跟在这个try后的finally{}里的code会不会执行,什么时候执行?
class Solution {
private static int method1() {
try {
int a = 10 / 1;
System.out.println("num is " + a);
return 0;
} finally {
System.out.println("finally");
}
}
public static void main(String[] args) {
// num is 10
// finally
Solution.method1();
}
}
看上面输出,finally里的code会执行,在try里面的return执行之前执行。
Java中的final关键字有哪些作用?
- final修饰类时,表明这个类不能被继承
- final修饰方法,表明方法不能被重写
- final修饰变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改,如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象
当一个线程进入一个对象的synchronized方法后,其他线程是否可进入此对象的次方法?
不能进入
一个.java源文件中是否可以包括多个类(不是内部类)?有什么限制?
一个.java的源文件中是可以包含多个类的,但是public类只能有一个,并且类名要和文件名相同,如果有两个public类 就会报出以下的错误
可以看到提示Test2应该被定义到一个Test2.java文件中
将Test2的的public去掉,即正常并且在Test1中可以使用
最后会被编译为2个class文件
下列程序段,数据的结果是什么?
class Solution {
public void trythis() {
try {
System.out.println("1");
problem();
} catch (RuntimeException x) {
System.out.println("2");
return;
} catch (Exception x) {
System.out.println("3");
return;
} finally {
System.out.println("4");
}
System.out.println("5");
}
private void problem() throws Exception{
throw new Exception();
}
public static void main(String[] args) {
Solution solution = new Solution();
solution.trythis();
}
}
输入为
1
2
4
设有一组关键词序列{5,8.14,20,31,55,78,81,93,97,11},使用二分法查找关键字93需要多少次比较
一般是让写二分查找代码,简单写一下吧,次数自己模拟一下就行
// 从list中找到target所在的下标,如果找不到,返回-1
public int binsearch(List<Integer> list, int target) {
int left = 0;
int right = list.size() - 1;
//注意是小于等于,如从123456中查找6,没等于不行
while(left <= right) {
int mid = (left + right) / 2;
if(target == list.get(mid)) {
return mid;
}
if(target > list.get(mid)) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
getValue(2)的结果是10
getValue(4)的结果是18
很简单的2个题,不再说了
下面关于abstract关键字描述错误的是
abstract类的子类必须实现其超类的所有abstract方法(错误的)
看如下代码,不会报错,所以不用实现
abstract class Father {
public abstract void show();
}
public abstract class Son extends Father{
}
下面是一颗树,请用某种方式将其转为二叉树,同时写出先序遍历
树转二叉树有一个法则
(1)树中所有相同双亲结点的兄弟结点之间加一条连线;
(2)对树中不是双亲结点的第一个孩子的结点,只保留新添加的该结点与左兄弟结点之间的连线,删去该结点与双亲结点之间的连线;
(3)整理所有保留的连线,根据连线摆放成二叉树的结构,转换完成。
是左子树还是右子树的一个法则是,左儿子,右兄弟(儿子是左子树,兄弟是右子树)
题目中将树转为二叉树的过程如下
写出先序遍历,上口诀
前序遍历:根,左,右
中序遍历:左,根,右
后序遍历:左,右,根
先序遍历为ABEFCGDH
在Java中,如何跳出当前的多重嵌套循环,两种方式实现?如数组int arr[][]={{1,2,3},{4,5,6,7},{8,9,5}}
找到数值5打印并跳出循环
标记退出这种方式我就不写了,写一个大多数人不知道的骚操作,这里先演示一下retry的使用
break retry 跳到retry处,且不再进入循环
continue retry 跳到retry处,且再次进入循环
public static void main(String[] args) {
breakRetry();
continueRetry();
}
private static void breakRetry() {
int i = 0;
retry:
for (; ; ) {
System.out.println("start");
for (; ; ) {
i++;
if (i == 4)
break retry;
}
}
//start 进入外层循环
//4
System.out.println(i);
}
private static void continueRetry() {
int i = 0;
retry:
for(;;) {
System.out.println("start");
for(;;) {
i++;
if (i == 3)
continue retry;
System.out.println("end");
if (i == 4)
break retry;
}
}
//start 第一次进入外层循环
//end i=1输出
//end i=2输出
//start 再次进入外层循环
//end i=4输出
//4 最后输出
System.out.println(i);
}
class Solution {
public static void main(String[] args) {
List<List<Integer>> list = new ArrayList<>();
list.add(Arrays.asList(1, 2, 3));
list.add(Arrays.asList(4, 5, 6, 7));
list.add(Arrays.asList(8, 9, 5));
retry:
for (int i = 0; i < list.size(); i++) {
List<Integer> tempList = list.get(i);
for (int j = 0; j < tempList.size(); j++) {
if (tempList.get(j) == 5) {
System.out.println("5");
break retry;
}
}
}
// 5
// end
System.out.println("end");
}
}
删除list中指定的所有元素,例如List<Integer>();如果存储的数据是[1,2,3,2,4,5,2]删除所有数值等于2的元素?
这个需要注意的一点就是尽量不要用list.remove(),因为要注意的细节比较多,很容易出错,我也不想解释了,有兴趣的可以看一下这篇文章
https://blog.csdn.net/qq_42986107/article/details/81988470
用迭代器模式删除就行
class Solution {
private static void removeElement(List<Integer> list, int target) {
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
int value = it.next();
if (value == target) {
it.remove();
}
}
}
public static void main(String[] args) {
List<Integer> tempList = Arrays.asList(1, 2, 3, 2, 4, 5, 2);
List<Integer> list = new ArrayList<>(tempList);
removeElement(list, 2);
for (int i = 0; i < list.size(); i++) {
// 1 3 4 5
System.out.print(list.get(i) + " ");
}
}
}
输出如下代码的输出结果
class HelloA {
// 构造函数
public HelloA() { System.out.println("Hello A"); }
// 构造代码块
{ System.out.println("I'm A class");}
// 静态代码块
static { System.out.println("static A"); }
}
public class HelloB extends HelloA {
public HelloB() { System.out.println("Hello B"); }
{ System.out.println("I'm B class"); }
static { System.out.println("static B"); }
public static void main(String[] args) {
new HelloB();
}
}
从这个题目也可以看出一个.java文件可以包括多个类
简单的类加载顺序,上口诀
- 父类的静态(静态代码块,静态成员变量),子类的静态(静态代码块,静态成员变量)
- 父类的非静态(构造代码块,非静态成员变量),父类的构造函数
- 子类的非静态(构造代码块,非静态成员变量),子类的构造函数
所以写出如下输出就很容易了
static A
static B
I'm A class
Hello A
I'm B class
Hello B
剩下的编程题没多大难度,就不写了
快陪练
算法题没啥难度,简单写一下
二叉树有三种遍历方式
前序遍历:根,左,右
中序遍历:左,根,右
后序遍历:左,右,根
发现规律没?左右的位置始终不变,前序遍历,根在前面,中序遍历,根在中间,以此类推。
前序遍历:A B C D E F
中序遍历:C B D A E F
后序遍历:C D B F E A
常用Linux命令
简单说几个,ls mkdir 面试就不用写了,简单的命令大家都会,top,free之类的写写
less — print LESS
less 按页或按窗口打印文件内容。在查看包含大量文本数据的大文件时是非常有用和高效的。你可以使用Ctrl+F向前翻页,Ctrl+B向后翻页。
ping
ping 通过发送数据包ping远程主机(服务器),常用与检测网络连接和服务器状态。
如 ping www.baidu.com
su — Switch User
su 用于切换不同的用户。即使没有使用密码,超级用户也能切换到其它用户。
top — Top processes
top命令会默认按照CPU的占用情况,显示占用量较大的进程,可以使用top -u 查看某个用户的CPU使用排名情况。
OSI七层模型
http请求方式与区别
(1)对参数的数据类型,GET只接受ASCII字符,而POST没有限制,允许二进制。
(2)GET在浏览器回退/刷新时是无害的,而POST会再次提交请求。
(3)GET请求只能进行url编码(application/x-www-form-urlencoded),而POST支持多种编码方式(application/x-www-form-urlencoded 或 multipart/form-data),可以为二进制使用多重编码。
(4)POST 比 GET 更安全,因为GET参数直接暴露在URL上,POST参数在HTTP消息主体中,而且不会被保存在浏览器历史或 web 服务器日志中。
(5)对参数数据长度的限制,GET方法URL的长度是受限制的,最大是2048个字符,POST参数数据是没有限制的。
(6)GET请求会被浏览器主动缓存,POST不会,除非手动设置。
(7)GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
(8)GET请求可被收藏为书签,POST不能。
http常见的状态码
我单写一篇文章来描述http状态码
200 OK //客户端请求成功
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
访问网页的过程,越详细越好
详细过程单开一篇文章
反向打印链表的值
如链表的值为1-2-3-4,打印出的值为4 3 2 1
将值放在数组中,然后反向遍历数据输出,这种方法不太优雅
正确的方式如下,一个递归搞定
public Class Node {
int value;
Node next;
}
public static void printNode(Node node) {
if (node == null) return;
printNode(node.next);
System.out.println(node.val);
}
主键用自增id好,还是uid好?
当然是自增id了,自主键的数据结构是B+树,用自增id不会造成树的分裂,uid不规则,会造成树的分裂,效率比较低
给一个数组有n个值,求m个值和为24的所有组合
回溯,DFS,算法均可,不写代码了,知道思路即可
数据单向链表中倒数第n个节点的值
我刚开始是,遍历一遍链表,求出长度,然后再遍历一变到n-k,结果告知这种方法效率比较低
后来想到,用2个指针,中间相隔n个距离,当一个指针到了尾节点时,另一个节点正好指向倒数第n个节点
其他就是类似一些string,stirngbuffer,stringbuild的区别
nio和bio的区别
抽象类和接口的区别、
展心展力
Java中byte,short,char,int,float各占几个字节
Java8种基本数据类型
整数类型:byte(1字节) short(2字节) int(4字节) long(8字节)
浮点类型:float(4字节) double(8字节)
字符类型:char(2字节)可以存储一个汉字
布尔类型:boolean
(JVM规范指出boolean当做int处理,也就是4字节,boolean数组当做byte数组处理,这样我们可以得出boolean类型占了单独使用是4个字节,在数组中是确定的1个字节)
如何将内容为整数的字符串解析为整数
Long.valueof()
关键字volatile的作用
不能保证原子性,只能保证可见性,有序性,我公号上对volatile的作用写的很清楚
String能否被继承,原因
不能,String类被final修饰
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
总结一下final关键字的作用
- final修饰类时,表明这个类不能被继承
- final修饰方法,表明方法不能被重写
- final修饰变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改,如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象
ArrayLIst如何扩容
数组大小变为原来的1.5倍,将原来的内容复制到新数组
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 从这个看出新数组是原来数组大小的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
一个servlet被请求10次,会创建几个事例
只会创建一个实例
一般Servlet只初始化一次(只有一个实例)。对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此Servlet的service()方法,将这两个对象作为参数传递给该方法。如此重复以上的循环,但无需再调用init()方法。
异常处理
最后输出9,很简单的一道题
列举Spring MVC常用注解和含义(常用)
@Controller
@RequestMapping
@Autowired
@ResponseBody
Mybatis中$和#的区别,哪个能防止SQL注入
$底层用的是Statement ,字符串拼接SQL,可能会有SQL注入
#底层用的是PreparedStatement,使用预编译语句
Java线程生命周期图?
这个很重要,一定要多看看
列举你了解的JDK命令工具和JVM启动参数,并说明其用法
名称 | 主要作用 |
---|---|
jps | 显示指定系统内所有HotSpot虚拟机进程 |
jstat | 收集HotSpot虚拟机个方面的运行数据 |
jinfo | 显示虚拟机配置信息 |
jmap | 生成虚拟机的内存转储快照(heapdump)文件 |
jhat | 在浏览器上分析heapdump文件 |
jstack | 显示虚拟机的线程快照 |
-Xmx4550m 最大可用内存为4550m
-Xmx4550m 启动时分配的内存为4550m
-Xss 每个线程分配的内存大小
varchar char的区别
char(10) ,当输入的是“abc”这三个字符时,占用的空间一样是10个字符,包括7个空字符
varchar(10),当输入的是“abc”这三个字符时,占用的空间是3个字符,额外1个或2个字符用来记录字符的长度
varchar省空间,char效率高
char还有的优点如下:
一,存储很短的信息,比如门牌号码101,201……这样很短的信息应该用char,因为varchar还要占个byte用于存储信息长度,本来打算节约存储的现在得不偿失。
二,固定长度的。比如使用uuid作为主键,那用char应该更合适。因为他固定长度,varchar动态根据长度的特性就消失了,而且还要占个长度信息。
三,十分频繁改变的column。因为varchar每次存储都要有额外的计算,得到长度等工作,如果一个非常频繁改变的,那就要有很多的精力用于计算,而这些对于char来说是不需要的。
主键和索引的区别
主键一定是唯一性索引,唯一性索引不一定就是主键
一个表中可以有多个索引,但只能有一个主键
主键列不允许为空值,索引列可以为空值
索引可以提高查询的速度
MySQL行锁和表锁的含义,并说明他们之间的区别
表锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突概率高,并发度最低
行锁:开销大,加锁慢,会出现死锁;锁定粒度小,发生冲突概率低,并发度高
页锁:开销和加锁速度介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般
MySQL服务占用CPU 100%,如何排查问题
查询慢SQL日志,找到执行慢的SQL语句,排查错误
事务隔离级别有哪些?
未提交读
提交读
重复读
序列化
LeetCode原题,不太难,直接上代码
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char a = s.charAt(i);
if (stack.size() == 0) {
stack.push(a);
continue;
}
char peekChar = stack.peek();
if ((peekChar == '(' && a == ')') || (peekChar == '[' && a == ']') ||
(peekChar == '{' && a == '}')) {
stack.pop();
} else {
stack.push(a);
}
}
return stack.size() == 0 ? true : false;
}
}
LeetCode原题
将每个字符串排序一下,key=排序后的字符, value=原始的字符,放在map中即可
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (int i = 0; i < strs.length; i++) {
String key = sort(strs[i]);
List<String> list = map.get(key);
if (list == null) {
list = new ArrayList<>();
list.add(strs[i]);
map.put(key, list);
} else {
list.add(strs[i]);
}
}
List<List<String>> resultList = new ArrayList<>();
for (List<String> list : map.values()) {
resultList.add(list);
}
return resultList;
}
private String sort(String str) {
char[] charArray = str.toCharArray();
Arrays.sort(charArray);
return new String(charArray);
}
}
挺简单的一个SQL题,就不写了
京东
建了索引是否会用到
说几个自己熟悉的设计模式
画一个装饰者模式
反转链表
spring boot没有web.xml怎么运行?
netty
redis有几种基本数据类型?其中有序集合是啥?
string(字符串类型)
hash(散列类型)
list(列表类型)
set(集合类型)
zset(有序集合类型)
git fetch和git pull的区别
jmap和jstack的作用
这几个工具全记住得了,经常被问,jstack的详细作用我在公号Java识堂上写了,CPU100%的那篇文章
名称 | 主要作用 |
---|---|
jps | 显示指定系统内所有HotSpot虚拟机进程 |
jstat | 收集HotSpot虚拟机个方面的运行数据 |
jinfo | 显示虚拟机配置信息 |
jmap | 生成虚拟机的内存转储快照(heapdump)文件 |
jhat | 在浏览器上分析heapdump文件 |
jstack | 显示虚拟机的线程快照 |
宝贝格子
aop和ioc用了什么模式?
数据库优化策略
消除过多的if else 用什么模式?
搜索引擎原理
es
redis的五种基本数据类型是啥?
redis的哨兵机制
参考博客
boolean到底占用几个字节
[1]https://blog.csdn.net/YuanMxy/article/details/74170745