
61. 旋转链表
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
示例 1:
输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]
示例 2:
输入:head = [0,1,2], k = 4
输出:[2,0,1]
思路: 求长度,取模最终移动多少位,重新拼接
1 | /** |
86. 分隔链表
给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
示例 1:
输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]
示例 2:
输入:head = [2,1], x = 2
输出:[1,2]
思路: 做两个链表,然后拼接起来即可
1 | /** |
146. LRU 缓存
请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
示例:
输入
[“LRUCache”, “put”, “put”, “get”, “put”, “get”, “put”, “get”, “get”, “get”]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]
解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
思路:
栈+map
1 | class LRUCache { |
104. 二叉树的最大深度
给定一个二叉树 root ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:3
示例 2:
输入:root = [1,null,2]
输出:2
思路:
树比递归
1 | /** |
100. 相同的树
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例 1:
输入:p = [1,2,3], q = [1,2,3]
输出:true
示例 2:
输入:p = [1,2], q = [1,null,2]
输出:false
示例 3:
输入:p = [1,2,1], q = [1,1,2]
输出:false
思路:
树必递归
1 | /** |
226. 翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
示例 1:
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
示例 2:
输入:root = [2,1,3]
输出:[2,3,1]
示例 3:
输入:root = []
输出:[]
思路:
递归
1 | /** |
101. 对称二叉树
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
思路:
树必递归
1 | /** |
792. 匹配子序列的单词数
给定字符串 s 和字符串数组 words, 返回 words[i] 中是s的子序列的单词个数 。
字符串的 子序列 是从原始字符串中生成的新字符串,可以从中删去一些字符(可以是none),而不改变其余字符的相对顺序。
例如, “ace” 是 “abcde” 的子序列。
示例 1:
输入: s = “abcde”, words = [“a”,”bb”,”acd”,”ace”]
输出: 3
解释: 有三个是 s 的子序列的单词: “a”, “acd”, “ace”。
Example 2:
输入: s = “dsahjpjauf”, words = [“ahjpjau”,”ja”,”ahbwzgqnuk”,”tnmlanowax”]
输出: 2
思路:
- 如果暴力,为了判断是不是子串,大量重复
- 另外,给的带判断数组,也有大量重复,重复相乘,笛卡尔积得复杂度
- 思路,每个带判断字符串做一个对象,自己维护指针,减少重复。
- 注意点, 集合循环删除,要用迭代器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71package h.xd.algo;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Main72 {
public static void main(String[] args) {
new Solution72().numMatchingSubseq("abcde",new String[]{"a","bb","acd","ace"});
}
}
class Solution72 {
public int numMatchingSubseq(String s, String[] words) {
char[] scs = s.toCharArray();
Map<String,SubStr> dic = new HashMap();
for(int i=0;i<words.length;i++){
if(dic.get(words[i]) != null){
dic.get(words[i]).count++;
continue;
}
SubStr ss = new SubStr(words[i]);
dic.put(words[i], ss);
}
int rst = 0;
for(int i=0;i<scs.length;i++){
Iterator<Map.Entry<String, SubStr>> iterator = dic.entrySet().iterator();
while(iterator.hasNext()){
SubStr tmp = iterator.next().getValue();
if(tmp.isSub) {
rst+=tmp.count;
iterator.remove();
continue;
}
tmp.comeChar(scs[i]);
}
}
for(SubStr tmp:dic.values()){
if(tmp.isSub) rst+=tmp.count;
}
return rst;
}
}
class SubStr{
char[] wc;
int begin;
int length;
int count;
boolean isSub;
public SubStr(String word){
this.wc = word.toCharArray();
this.begin=0;
this.length =this.wc.length;
this.isSub = false;
this.count = 1;
}
public void comeChar(char c){
if(c == this.wc[this.begin]){
this.begin++;
if(this.begin == this.length){
this.isSub= true;
}
return;
}
return;
}
}
System.gc() 到底会不会触发 GC?
面试官如果这么问,可以这么回答:
System.gc() 和 Runtime.gc() 只是”建议”JVM 进行垃圾回收,是否执行由 JVM 自己决定。现代 JVM 的 GC 策略通常会忽略这个调用,以优化性能。可以通过 -XX:+DisableExplicitGC 禁用 System.gc(),或者用 -XX:+ExplicitGCInvokesConcurrent 让其触发并发 GC。
听完如果点头,那就稳了!如果他继续追问”那你觉得 System.gc() 什么时候应该用?”
你可以再补充:一般情况下,我们不会手动调用 System.gc(),除非是在一些特定的环境下,比如:
- 进行性能测试时,确保 GC
- 影响最小处理大对象,手动释放内存
- 游戏或者图形渲染应用,控制 GC 运行时机
但大部分情况下,让 JVM 自己决定 GC 时机才是最好的选择。
总结System.gc() 和 Runtime.gc(): ✅ 只是一个“请求”,JVM 可能会忽略
✅ 不保证立刻触发 GC
✅ 在现代 JVM 中通常不需要手动调用
✅ 可以用 -XX:+DisableExplicitGC 禁用
- 本文标题:Letcode刷题记录
- 本文作者:形而上
- 创建时间:2019-01-30 00:00:00
- 本文链接:https://deepter.gitee.io/2019_01_30_letcode/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!