阴天在开灯的房间
目录
1.Lee 77 组合
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res= new ArrayList<>();
Deque<Integer> path = new ArrayDeque<>();
dfs(n,k,1,path,res);
return res;
}
private void dfs(int n, int k, int cur, Deque<Integer> path, List<List<Integer>> res) {
if (path.size() == k){
res.add(new ArrayList<>(path));
return; // 递归的终止条件;
}
// 遍历可能的搜索起点
for (int j = cur; j <= n ; j++) {
// 向集合中添加当前的数
path.addLast(j);
// 求包含当前数字 cur时 ,子问题cur+1 到n 的组合。只遍历从cur+1开始之后的 数字之前的数字不会再有。
dfs(n,k,j+1,path,res);
// 进行回溯操作
path.removeLast();
}
}
选择1
1.下面的选项当中那个不属于java运行时数据区域
工作内存
虚拟机栈
堆
方法区
题解:工作内存和主存java内存模型中的概念。 java运行时数据区域包含: 程序计数器 java虚拟机栈 本地方法栈 堆 方法区 直接内存
2.关于jvm 中不正确的
启动一个java程序,本质是在java虚拟机中运行class字节码
java程序只能运行在Hotpost虚拟机中
java虚拟机可以自动管理java进程的内存
jdk中包含了jvm,但是jre中不包含。
题解: java虚拟机除了官方的hotshot外 还有其他的虚拟机实现 对java程序来说 也可以运行在不同的虚拟机当中 jvm,jdk, jre的关系: jdk包含jre,jre包含jvm。
3.java程序,在什么时候会执行类加载
创建类的实例
使用java.exe 命令来运行某个主类的main方法
使用反射来执行某个类的静态方法
使用new创建子类的实例对象时,父类需要先执行类加载
题解:在上面的场景当中如果没有执行过类的加载,则会先执行类的加载
在java程序中,垃圾回收如何判断一个对象是否可以回收
基于引用计数算法
基于可达性分析算法
基于复制算法
基于标记-整理算法
题解:在垃圾回收时,判断对象是否可以回收的时候,有引用计数算法和可达性分析算法两种,java是基于可达性分析算法实现的。
垃圾回收的算法有
标记清楚算法
复制算法
标记-整理算法
分代收集算法
题解:垃圾回收的算法包括: 标记-清楚算法:最基础的算法,后续的收集算法都是基于这种思路并对其不足加以改进而已 复制算法:新生代的收集算法 标记-整理算法:老年代的收集算法 分代收集算法:没有具体的算法实现,只是针对不同区域垃圾的特性,采取不同的回收策略。
oj练习2
Lee_182 查找重复的电子邮箱
1.使用group by 对 email 分组,再使用 having 将重复的 email 筛选出来。
select Email from Person group by Email having count(Email) >1 ;
Lee_24 两两交换链表
public ListNode swapPairs(ListNode head) {
ListNode dumHead = new ListNode();
dumHead.next = head;
ListNode tmp = dumHead;
while (tmp.next != null && tmp.next.next != null){
ListNode node1 = tmp.next;
ListNode node2 = tmp.next.next;
tmp.next = node2;
node1.next = node2.next;
node2.next = node1;
tmp = node1;
}
return dumHead.next;
// 此时的 dumHead.next 为真正的头结点 而返回head 就会把2遗漏
}
选择02
1.关于新生代的说法,不正确的是
java对象优先分配在新生代中
新生代是方法区中的一块
新生代包含一块eden区和两个survivor
新生代垃圾回收速度比老年代快。
题解:新生代,老年代都是针对堆内存,在gc(garbage collection)中的划分
2.关于cms垃圾回收器,下面的 说法正确的是
cms是所有的垃圾回收器当中最好的
它是一款单线程的垃圾回收器
对于性能的要求高的java应用 可以使用cms 垃圾收集器
cms是老年代的垃圾回收器、
对于编程语言来讲没有最好的,只有在合适的场景下,使用合适的语言。相应的,垃圾收集器也是一样,每一款收集器都有不同的使用场景 CMS是多线程的 CMS更适合用户体验优先的应用,对吞吐量性能来讲,可以容忍一定程度的下降
3.关于volatile 的说法正确得是
volatile 可以保证变量在多线程中的任何操作都是安全的
volatile 可以修饰方法,表示该方法是线程安全的
volatile 可以保证变量在多线程中"读"操作是安全的
volatile 也可以满足原子性
volatile变量在多线程中的写操作,可能是不安全的 volatile只能修饰成员变量 静态变量 volatile 可以保证可见性有序性 不能保证原子性
4.关于synchronized 的说法,正确的是()
synchronized 可以使用在静态方法和实例方法上
synchronized一定可以保证多线程执行某段代码是安全的
synchronized 是基于对象头来进行加锁的
synchronized 的代码,在一个时间上,只能有一个线程执行。
多线程要使用 synchronized 来保证某段代码的线程安全,需要使用同一把锁 ,即时同一个对象来加锁 synchronized 修饰的一段代码 可以保证多线程同步互斥的执行 (在同一时间 只能有一个线程执行),但是需要有一个前提,使用同一个对象加锁。
关于程序和进程,下面的说法正确的是
两者是相同的
程序是静态的可执行文件,进程是运行中的程序
Main.java是一个程序
Main.class是一个程序
题解: 程序和进程是不同的概念 前者是静态的,表示为硬盘中的可执行文件 后者为动态的 表示为内存中运行起来的程序代码 对java程序来说 Main.java 要运行 是使用java Main 的命令来执行 本质是启动的java虚拟机 而不是Main程序
代码2
Lee_137
public int singleNumber(int[] nums) {
HashMap<Integer,Integer> hashMap = new HashMap<>();
for (int num: nums) {
hashMap.put(num,hashMap.getOrDefault(num,0)+1);
// 第一次的输入 得到默认的值 0 再加1
// 第二次输入的时候 查看有没有num 有的话就得到存储的值 1 再加上1
// 没有的话就得到默认的值 0 再加上1;
}
int res = 0;
for (Map.Entry<Integer,Integer> entry : hashMap.entrySet()){
int n = entry.getKey(); int o = entry.getValue();
if (o == 1){
res = n;
break;
}
}
return res;
}
hashMap.getOrDefault的用法
当map集合中有这个key值的时候,就使用这个key值,如果没有就使用默认的defaultValue HashMap<String, String> map = new HashMap<>(); map.put("name", "cookie"); map.put("age", "18"); map.put("sex", "女"); String name = map.getOrDefault("name", "random"); System.out.println(name);// cookie,map中存在name,获得name对应的value int score = map.getOrDefault("score", 80); System.out.println(score);// 80,map中不存在score,使用默认值80
关于Map的遍历方式: // 通过 Map.entrySet 遍历key 和 value for(Map.Entry<K,V> entry : map.entrySet()){ System.out.println("key=" + entry.getKey() + " and value =" + entry.getValue) }