牛客题
1.两数之和
使用hashmap解决
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> m = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (m.get(target - nums[i]) != null) {
return new int[]{m.get(target - nums[i])+1, i+1};
}
m.put(nums[i], i);
}
return new int[]{0, 0};
}
思想:从数组中挑出一个数,判断map中是否有其需要的数
如果有,则返回结果
如果没有,将这个数放入map中
继续挑下一个数
设计LRU(Least Recently Used)
设计LRU(最近最少使用)缓存结构,该结构在构造时确定大小,假设大小为 k ,并有如下两个功能
- set(key, value):将记录(key, value)插入该结构
- get(key):返回key对应的value值
思路:
1.想到队列(先进先出)
but 如果使用get()方法,无法快速的从队列中提出相应的数组
2.数组(带索引,可通过判断大小决定先后,其次,可以通过给定的k值,决定数组的大小)
集合也可带索引(arraylist底层还是数组)
但是之后需要进行列表类元素的位置转换->so,选择链表可能更加合适
linkedlist<hashMap<Integer,Integer>>
java中有一个特别适合的类LinkedHashMap<>()
key是按照顺序存放的
import java.util.*;
public class Solution {
/**
* lru design
* @param operators int整型二维数组 the ops
* @param k int整型 the k
* @return int整型一维数组
*/
public class Solution {
public int[] LRU (int[][] operators, int k) {
HashMap<Integer,Integer> dic = new HashMap();
List<integer> list = new ArrayList<integer>();
List<integer> res = new ArrayList<integer>();
for(int i=0;i<operators.length;i++)
{
int[] temp = operators[i];
if(temp[0]==1) //更新操作;
{
if(list.size()>=k)
{
list.remove(0);
}
dic.put(temp[1],temp[2]);
if(list.contains(temp[1]))
{
list.remove(list.indexOf(temp[1]));
list.add(temp[1]);
}
else
{
list.add(temp[1]);
}
}
else
{
if(list.contains(temp[1]))
{
res.add(dic.get(temp[1]));
list.remove(list.indexOf(temp[1]));
list.add(temp[1]);
}
else
{
res.add(-1);
}
}
}
return res.stream().mapToInt(Integer::intValue)
.toArray();
}
}
2.较为常见的hashmap+双向链表
import java.util.*;
class LRUCache {
class Node {
int k, v;
Node l, r;
Node(int _k, int _v) {
k = _k;
v = _v;
}
}
int n;
Node head, tail;
Map<Integer, Node> map;
public LRUCache(int capacity) {
n = capacity;
map = new HashMap<>();
head = new Node(-1, -1);
tail = new Node(-1, -1);
head.r = tail;
tail.l = head;
}
public int get(int key) {
if (map.containsKey(key)) {
Node node = map.get(key);
refresh(node);
return node.v;
}
return -1;
}
public void put(int key, int value) {
Node node = null;
if (map.containsKey(key)) {
node = map.get(key);
node.v = value;
} else {
if (map.size() == n) {
Node del = tail.l;
map.remove(del.k);
delete(del);
}
node = new Node(key, value);
map.put(key, node);
}
refresh(node);
}
// refresh 操作分两步:
// 1. 先将当前节点从双向链表中删除(如果该节点本身存在于双向链表中的话)
// 2. 将当前节点添加到双向链表头部
void refresh(Node node) {
delete(node);
node.r = head.r;
node.l = head;
head.r.l = node;
head.r = node;
}
// delete 操作:将当前节点从双向链表中移除
// 由于我们预先建立 head 和 tail 两位哨兵,因此如果 node.l 不为空,则代表了 node 本身存在于双向链表(不是新节点)
void delete(Node node) {
if (node.l != null) {
Node left = node.l;
left.r = node.r;
node.r.l = left;
}
}
}
public class Solution {
/**
* lru design
* @param operators int整型二维数组 the ops
* @param k int整型 the k
* @return int整型一维数组
*/
public int[] LRU (int[][] operators, int k) {
List<Integer> list = new ArrayList<>();
LRUCache lru = new LRUCache(k);
for (int[] op : operators) {
int type = op[0];
if (type == 1) {
// set(k,v) 操作
lru.put(op[1], op[2]);
} else {
// get(k) 操作
list.add(lru.get(op[1]));
}
}
int n = list.size();
int[] ans = new int[n];
for (int i = 0; i < n; i++) ans[i] = list.get(i);
return ans;
}
}