标签:哈希表、链表、双向链表
思路:时间复杂度要求为O(1),用哈希表解决。哈希表的value存储双向链表节点。在双向链表中,建立一个虚拟头节点,一个虚拟尾节点。对操作过的节点,每次都将节点添加到头节点的后面,双向链表的最后一个节点存储的就是最近未使用的。
代码:
public class _146_LRU缓存 {
private Node first;
private Node last;
Map<Integer,Node> map;
private int capacity;
public _146_LRU缓存(int capacity) {
map = new HashMap<>(capacity);
this.capacity = capacity;
first = new Node();
last = new Node();
first.next = last;
last.prev = first;
}
public int get(int key) {
Node node = map.get(key);
if(node == null) return -1;
removeNode(node);
addAfterFirst(node);
return node.value;
}
public void put(int key, int value) {
Node node = map.get(key);
if(node != null){
node.value = value;
removeNode(node);
addAfterFirst(node);
}else{// 新添加一个key-value
if(map.size() == capacity){
//淘汰最近最少使用的node,删除最后一个(注意也要从map中删除)
map.remove(last.prev.key);
removeNode(last.prev);
}
map.put(key,node = new Node(key,value));
addAfterFirst(node);
}
}
private void removeNode(Node node) {
node.next.prev = node.prev;
node.prev.next = node.next;
}
private void addAfterFirst(Node node) {
node.next = first.next;
first.next.prev = node;
first.next = node;
node.prev = first;
}
private static class Node{
public int key;
public int value;
public Node prev;
public Node next;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
public Node() {
}
}
}
2._54_螺旋矩阵
标签:数组、矩阵
思路:将矩阵看成若干层,先输出最外层的元素,其次输出次外层的元素,直到输出最内层的元 素。
代码:
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> list = new ArrayList<>();
int top = 0;
int bottom = matrix.length - 1;
int left = 0;
int right = matrix[0].length - 1;
while(top <= bottom && left <= right){
// 从left top->right top
for(int i = left;i <= right;i++){
list.add(matrix[top][i]);
}
top++;
// 从right top->right bottom
for(int i = top;i <= bottom;i++){
list.add(matrix[i][right]);
}
right--;
if(top > bottom || left > right){
break;
}
// 从right bottom ->left bottom
for(int i = right;i >= left;i--){
list.add(matrix[bottom][i]);
}
bottom--;
// 从left bottom到left top
for(int i = bottom;i >= top;i--){
list.add(matrix[i][left]);
}
left++;
}
return list;
}
注意如果不在while循环中进行判断,在奇数行和偶数列会出问题。
3._7_整数反转
标签:数学
思路:
①取出整数的每一位
123 -> 321 = 3 * 100 + 2*10 +1
如果将最后的结果存储为int类型,当溢出时,会计算错误。应该借助更大类型来判断溢出情况。
代码:
public int reverse(int x) {
long res = 0;
while (x != 0) {
res = res * 10 + x % 10;
if(res > Integer.MAX_VALUE){
return 0;
}
if(res < Integer.MIN_VALUE){
return 0;
}
x /= 10;
}
return (int)res;
}
②公式法
判断计算出来的结果是否能正确的通过倒推法计算,如果数值相等,则计算正确;如果不相等,表示有溢出。
public int reverse(int x){
int res = 0;
while(x != 0){
int prevRes = res;
res = prevRes * 10 + x % 10;
if((res - x % 10) / 10 != prevRes) return 0;
x /= 10;
}
return res;
}