「这是我参与2022首次更文挑战的第38天,活动详情查看:2022首次更文挑战」。
导读
在刚刚结束的 每日算法&面试题,大厂特训二十八天 和 冲刺大厂每日算法&面试题,动态规划21天 的训练中我们一起打卡走了过来。但是学习不能停呀相信许多小伙伴也从之前的练习中取得了不错的成绩,从今天开始我们开始Java集训(算法&&面试题)第一天接着卷起来。
Java蓝桥集训
import java.util.*;
public class Main {
static int N = 100010;
static CII stk[] = new CII[N];
static int a[] = new int[N];
static int top;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
while(m -- > 0) {
int t = sc.nextInt();
int x = sc.nextInt();
if(t == 0) {
while(top > 0 && stk[top].t == 0) x = Math.max(x, stk[top -- ].x);
while(top >= 2 && stk[top - 1].x <= x) top -= 2;
stk[ ++ top] = new CII(0, x);
}
else if(top != 0) {
while(stk[top].t == 1) x = Math.min(x, stk[top -- ].x);
while(top >= 2 && stk[top - 1].x >= x) top -= 2;
stk[ ++ top] = new CII(1, x);
}
}
int l = 1, r = n, k = n;
for(int i = 1; i <= top; i ++ ) {
int x = stk[i].x;
if(stk[i].t == 0) {
while(r > x && l <= r) a[r -- ] = k -- ;
} else {
while(l < x && l <= r) a[l ++ ] = k -- ;
}
if(l > r) break;
}
if(top % 2 == 1)
while(l <= r) a[l ++ ] = k -- ;
else
while(l <= r) a[r -- ] = k -- ;
for(int i = 1; i <= n; i ++ )
System.out.print(a[i] + " ");
}
static class CII {
int t, x;
public CII(int a, int b) {
t = a; x = b;
}
}
}
解二:
这个想法比较简单只得了六十分
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
Integer[] arr= new Integer[n];
for(int i=1;i<=n;i++) {
arr[i-1]=i;
}
int m=sc.nextInt();
for(int i=0;i<m;i++) {
int a=sc.nextInt();
int b=sc.nextInt();
if(a==0) {
Arrays.sort(arr,0,b,Collections.reverseOrder());
}else {
Arrays.sort(arr,b-1,n);
}
}
for(int i:arr) {
System.out.print(i+" ");
}
}
}
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int a;
Set<Integer> set=new HashSet<Integer>(); //用来去重
List<Integer> list; //用来遍历,不能直接遍历set
//因为在遍历的过程中要往set增加
set.add(sc.nextInt());
while(n-->1){
a=sc.nextInt();
list=new ArrayList<>(set);
for (Integer in : list) { //遍历前面的种类,与新加入的砝码组合
if(in!=a)set.add(Math.abs(in-a)); //防止相减时出现0
set.add(in+a);
}
set.add(a);
}
System.out.println(set.size());
}
}
面试题
谈一谈缓存穿透、缓存击穿和缓存雪崩,以及各自的解决方案?
缓存穿透
问题:大量并发查询不存在的 KEY,在缓存和数据库中都不存在,同时给缓存和数据库
带来压力。
原因:一般而言,缓存穿透有 2 种可能性:业务数据被误删,导致缓存和数据库中都没
有数据。恶意进行 ddos 攻击。
分析:为什么会多次透传呢?不存在 一直为空,需要注意让缓存能够区分 KEY 不存在和
查询到一个空值。
解决办法:缓存空值的 KEY,这样第一次不存在也会被加载会记录,下次拿到有这个
KEY。Bloom 过滤或 RoaingBitmap 判断 KEY 是否存在,如果布隆过滤器中没有查到
这个数据,就不去数据库中查。在处理请求前增加恶意请求检查,如果检测到是恶意攻击,
则拒绝进行服务。完全以缓存为准,使用延迟异步加载的策略(异步线程负责维护缓存的
数据,定期或根据条件触发更新),这样就不会触发更新。
缓存击穿
问题:某个 KEY 失效的时候,正好有大量并发请求访问这个 KEY。
分析:跟穿透其实很像,属于比较偶然的。
解决办法:KEY 的更新操作添加全局互斥锁。完全以缓存为准,使用延迟异步加载的策
略(异步线程负责维护缓存的数据,定期或根据条件触发更新),这样就不会触发更新。
缓存雪崩
问题:当某一时刻发生大规模的缓存失效的情况,导致大量的请求无法获取数据,从而将
流量压力传导到数据库上,导致数据库压力过大甚至宕机。
48
原因:一般而言,缓存雪崩有 2 种可能性:大量的数据同一个时间失效:比如业务关系
强相关的数据要求同时失效 Redis 宕机
分析:一般来说,由于更新策略、或者数据热点、缓存服务宕机等原因,可能会导致缓存
数据同一个时间点大规模不可用,或者都更新。所以,需要我们的更新策略要在时间上合
适,数据要均匀分享,缓存服务器要多台高可用。
解决办法:更新策略在时间上做到比较平均。如果数据需要同一时间失效,可以给这批数
据加上一些随机值,使得这批数据不要在同一个时间过期,降低数据库的压力。使用的热
数据尽量分散到不同的机器上。多台机器做主从复制或者多副本,实现高可用。做好主从
的部署,当主节点挂掉后,能快速的使用从结点顶上。实现熔断限流机制,对系统进行负
载能力控制。对于非核心功能的业务,拒绝其请求,只允许核心功能业务访问数据库获取
数据。服务降价:提供默认返回值,或简单的提示信息