一、随想录ACM
1、区间和
import java.util.*;
class Main{
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int[] ans=new int[n];
int[] pre=new int[n];
for(int i=0;i<n;i++){
ans[i]=scanner.nextInt();
}
for(int i=0;i<n;i++){
pre[i]=(i==0?0:pre[i-1])+ans[i];
}
while(scanner.hasNext()){
int fir=scanner.nextInt(),las=scanner.nextInt();
System.out.println(pre[las]-(fir==0?0:pre[fir-1]));
}
}
}
2、均匀分配
import java.util.*;
class Main{
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int m=scanner.nextInt();
int[][] ans=new int[n][m];
int sum=0;
for(int i=0;i<n*m;i++){
ans[i/m][i%m]=scanner.nextInt();
sum+=ans[i/m][i%m];
}
int res=Integer.MAX_VALUE/2;
int temp=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
temp+=ans[i][j];
}
res=Math.min(res,Math.abs(sum-2*temp));
}
temp=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
temp+=ans[j][i];
}
res=Math.min(res,Math.abs(sum-2*temp));
}
System.out.println(res);
}
}
3、快速排序代码
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] arr = {9, 7, 5, 11, 12, 2, 14, 3, 10, 6};
System.out.println("排序前:" + Arrays.toString(arr));
quickSort(arr);
System.out.println("排序后:" + Arrays.toString(arr));
}
public static void quickSort(int[] arr) {
if (arr == null || arr.length <= 1) return;
quickSort(arr, 0, arr.length - 1);
}
private static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int pivotIndex = partition(arr, low, high); // 获取基准点位置
quickSort(arr, low, pivotIndex - 1); // 递归左子数组
quickSort(arr, pivotIndex + 1, high); // 递归右子数组
}
}
private static int partition(int[] arr, int low, int high) {
int pivot = arr[high]; // 选择末尾元素为基准
int i = low - 1; // 小于基准的区域的右边界
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
swap(arr, i, j); // 将较小元素移到左侧区域
}
}
swap(arr, i + 1, high); // 将基准元素放到正确位置
return i + 1;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
二、语雀-Redis面试题
1、Redis 的过期策略是怎么样的?
2、Redis的内存淘汰策略是怎么样的?
3、什么是热Key问题,如何解决热key问题
1. 多级缓存
2. 热key拆分
4、什么是大Key问题,如何解决?
1. 处理Big Key
5、什么是缓存击穿、缓存穿透、缓存雪崩?
1. 缓存穿透
1.1 缓存空值
1.2 布隆过滤器
2. 缓存击穿
2.1 异步定时更新
2.2 互斥锁
3. 缓存雪崩
3.1 不同过期时间
3.2 集群
6、什么情况下会出现数据库和缓存不一致的问题?
7、如何解决Redis和数据库的一致性问题
1. 为什么删缓存而不是更新
2. 先删除缓存后更新数据库(错误)
3. 先更新数据库后删除(正确)
4. 延迟双删
5. 更新数据库,基于 binlog 监听进行缓存删除
8、Redis如何实现延迟消息?
1. zset
2. Redission
9、Redis如何实现发布/订阅?
1. 优点与缺点
10、如何用SETNX实现分布式锁?
public class RedisDistributedLock {
private final JedisPool jedisPool;
public RedisDistributedLock(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
public boolean tryLock(String lockKey, String requestId, int expireTime) {
try (Jedis jedis = jedisPool.getResource()) {
String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
return "OK".equals(result);
}
}
public boolean unlock(String lockKey, String requestId) {
try (Jedis jedis = jedisPool.getResource()) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey),
Collections.singletonList(requestId));
return Long.parseLong(result.toString()) == 1L;
}
}
}
1. 优点与缺点
11、如何用Redisson实现分布式锁?
12、什么是RedLock,他解决了什么问题?
1. 被废弃
13、为什么ZSet 既能支持高效的范围查询,还能以 O(1) 复杂度获取元素权重值?
✅为什么ZSet 既能支持高效的范围查询,还能以 O(1) 复杂度获取元素权重值?
14、Redisson的watchdog机制是怎么样的?
1. 通过Lua脚本续期
2. 指定超时时间不会续期
3. 只有unlock才会停止续期
首先,就是我们上面讲过的那种,如果一个锁的unlock方法被调用了,那么就会停止续期。
15、什么是Redis的渐进式rehash
1. 如何查询
2. 与ConcurrentHashMap的扩容对比
1. 核心目标
Redis 的渐进式 Rehash 和 ConcurrentHashMap 的扩容都旨在解决数据结构动态扩容时的性能问题,但侧重点不同。Redis 的渐进式 Rehash 主要服务于单线程高并发场景,通过分步迁移避免一次性数据迁移导致的长时间阻塞,从而保证主线程的响应性;而 ConcurrentHashMap 的扩容则针对多线程环境,通过减少锁竞争和并行化迁移操作,提升多核 CPU 下的扩容效率,确保高吞吐量。
2. 实现机制
Redis 的渐进式 Rehash 通过维护新旧两个哈希表,在每次命令执行时迁移少量旧表数据到新表,允许读写操作同时作用于新旧两表,保证数据一致性;ConcurrentHashMap 在扩容时采用分段锁机制(JDK 1.8+ 使用 CAS + synchronized),仅对需要迁移的桶加锁,读操作无锁化,写操作通过并行迁移多个桶来加速扩容过程,同时保证线程安全。
3. 关键区别
两者的核心差异体现在并发模型和迁移粒度上。Redis 作为单线程系统,渐进式 Rehash 依赖分步迁移和读写共存来平衡性能,但需同时占用新旧两表的内存;ConcurrentHashMap 在多线程环境下通过细粒度锁和批量迁移提升效率,扩容完成后立即释放旧表内存。此外,Redis 的 Rehash 触发条件与负载因子和内存相关,而 ConcurrentHashMap 的扩容则严格基于元素数量与容量的阈值比例。
4. 设计思想共性
两者均采用“分阶段处理”思想以优化性能:Redis 通过渐进式迁移将单次扩容的开销分散到多次操作中,避免阻塞主线程;ConcurrentHashMap 则通过并行迁移多个桶,利用多核 CPU 的计算能力加速扩容。此外,两者均允许短暂的数据不一致(如 Redis 新旧表共存时的读写分离,ConcurrentHashMap 扩容时的读写竞争),但通过最终一致性保证功能的正确性。
5. 总结
Redis 的渐进式 Rehash 和 ConcurrentHashMap 的扩容本质上是针对不同场景的优化方案:前者为单线程高并发设计,强调平滑过渡和低延迟;后者为多线程高吞吐量设计,注重并行化和资源利用率。尽管实现细节不同,但核心目标一致——在动态调整数据规模时,通过合理的机制设计最大化性能并最小化对业务的影响。
三、语雀-计网面试题
1、浏览器输入www.taobao.com回车之后发生了什么
2、对称加密和非对称加密有什么区别?
3、简单介绍一下DNS?
1. DNS解析
4、ping的原理是什么?
1. ping为什么不需要端口
5、什么是正向代理和反向代理?
正向代理(forward proxy):是一个位于客户端和目标服务器之间的服务器(代理服务器),为了从目标服务器取得内容,客户端向代理服务器发送一个请求并指定目标,然后代理服务器向目标服务器转交请求并将获得的内容返回给客户端。
6、什么是跨域访问问题,如何解决?
浏览器实施了同源策略,即网页中的脚本只能访问与其来源相同的资源。同源的定义包括协议(如http与https)、域名和端口号,如果这三者中有任何一个不同,就会被视为跨域请求。