1.Union-Find 算法
图论
class Solution {
public boolean equationsPossible(String[] equations) {
//使用图论,先用相等式在相等字符之间建立联通,然后再判断不等式是否破坏之前的联通
//如果破坏,返回false;否则返回true
UF uf=new UF(26);
for(String eq:equations){
if(eq.charAt(1)=='='){
char x=eq.charAt(0);
char y=eq.charAt(3);
uf.union(x-'a',y-'a');
}
}
for(String eq:equations){
if(eq.charAt(1)=='!'){
char x=eq.charAt(0);
char y=eq.charAt(3);
if(uf.connected(x-'a',y-'a')){
return false;
}
}
}
return true;
}
}
class UF{
private int count;//记录联通分量个数
private int[] parent;//若干棵树
private int[] size;//树的重量(这棵树的节点个数)
public UF(int n){
this.count=n;
parent=new int[n];
size=new int[n];
for(int i=0;i<n;i++){
parent[i]=i;//初始化指向自己,正常应该指向根节点
size[i]=1;//初始化大小为1
}
}
public void union(int p,int q){
int rootp=find(p);//找到p所在根节点
int rootq=find(q);//找到q所在根节点
if(rootp==rootq) return;
//将重量小的树接到重量大的树上
if(size[rootp]>size[rootq]){
parent[rootq]=rootp;
size[rootp]+=size[rootq];
}else{
parent[rootp]=rootq;
size[rootq]+=size[rootp];
}
count--;
}
public boolean connected(int p,int q){
int rootp=find(p);
int rootq=find(q);
return rootp==rootq;//如果根节点相同,则是相连通的
}
public int find(int x){
//找到节点x所在树的根节点
while(parent[x]!=x){
parent[x]=parent[parent[x]];//压缩树,减小树的高度
x=parent[x];
}
return x;
}
}
2. LRU 算法
Least Recently Used,是一种缓存淘汰策略,计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾位置,LRU是按访问的时序来淘汰。
LRU 缓存算法的核心数据结构是哈希链表, LinkedHashMap,双向链表和哈希表的结合体。查找快,增删也快。
class LRUCache {
int cap;
LinkedHashMap<Integer,Integer> cache=new LinkedHashMap<>();
public LRUCache(int capacity) {
this.cap=capacity;
}
public int get(int key) {
//如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
//O(1) 时间复杂度
if(cache.containsKey(key)){
makeRecently(key);
return cache.get(key);
}
return -1;
}
public void put(int key, int value) {
// 如果关键字已经存在,则变更其数据值
//如果关键字不存在,则插入该组「关键字-值」
//当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值
//O(1) 时间复杂度
if(cache.containsKey(key)){
cache.put(key,value);
makeRecently(key);
}else{
if(cache.size()>=this.cap){
//删除链表头部,迭代器第一个指向的就是链表头结点
int oldestKey=cache.keySet().iterator().next();
cache.remove(oldestKey);
}
cache.put(key,value);
}
}
public void makeRecently(int key){
int val=cache.get(key);
cache.remove(key);
cache.put(key,val);
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
3. LFU 算法
淘汰访问频次最低的数据
class LFUCache {
int cap;//最大容量
int minFreq;//记录最小频次
HashMap<Integer,Integer> keyToVal;
HashMap<Integer,Integer> keyToFreq;
HashMap<Integer,LinkedHashSet<Integer>> freqToKeys;
public LFUCache(int capacity) {
this.cap=capacity;
keyToVal=new HashMap<>();
keyToFreq=new HashMap<>();
freqToKeys=new HashMap<>();
this.minFreq=0;
}
public int get(int key) {
//如果键存在于缓存中,则获取键的值,否则返回-1
if(keyToVal.containsKey(key)){
increaseFreq(key);
return keyToVal.get(key);
}else{
return -1;
}
}
public void put(int key, int value) {
//如果键已存在,则变更其值
//如果键不存在,请插入键值对
//当缓存达到其容量时,则应该在插入新项之前,使最不经常使用的项无效
//当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近最久未使用的键
if(this.cap<=0) return;
if(keyToVal.containsKey(key)){
keyToVal.put(key,value);
increaseFreq(key);
}else{
if(keyToVal.size()>=this.cap){
removeMinFreqKey();
}
keyToVal.put(key,value);
keyToFreq.put(key,1);
freqToKeys.putIfAbsent(1,new LinkedHashSet<>());
freqToKeys.get(1).add(key);
this.minFreq=1;
}
}
private void removeMinFreqKey(){
LinkedHashSet<Integer> keyList=freqToKeys.get(this.minFreq);
int deleteKey=keyList.iterator().next();
//更新FK表
keyList.remove(deleteKey);
if(keyList.isEmpty()){
freqToKeys.remove(this.minFreq);
}
//更新KV表
keyToVal.remove(deleteKey);
//更新KF表
keyToFreq.remove(deleteKey);
}
private void increaseFreq(int key){
int freq=keyToFreq.get(key);
//更新KF表
keyToFreq.put(key,freq+1);
//更新FK表
freqToKeys.get(freq).remove(key);
//将key加入 freq + 1 对应的列表中
freqToKeys.putIfAbsent(freq+1,new LinkedHashSet<>());
freqToKeys.get(freq+1).add(key);
//如果freq对应的列表空了移除这个 freq
if(freqToKeys.get(freq).isEmpty()){
freqToKeys.remove(freq);
// 如果这个freq恰好是minFreq,更新minFreq
if(freq==this.minFreq){
this.minFreq++;
}
}
}
}
/**
* Your LFUCache object will be instantiated and called as such:
* LFUCache obj = new LFUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/