11.盛最多水的容器
java
package hot100;
public class lc11 {
/*
盛最多水的容器
给定一个长度为 n 的整数数组 height 。
有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
*/
public int maxArea(int[] nums){
int max = 0;
int left = 0;
int right = nums.length-1;
while(left < right){
int chang = right - left;
int kuang = Math.min(nums[left], nums[right]);
int area = chang*kuang;
max = Math.max(max,area);
if(nums[left] < nums[right]){
left++;
}else{
right--;
}
}
return max;
}
public static void main(String[] args){
int[] nums = new int[]{1,8,6,2,5,4,8,3,7};
lc11 solution = new lc11();
System.out.println("答案:" + solution.maxArea(nums));
}
}
49. 字母异位词分组
java
package hot100;
import java.util.*;
public class lc49 {
/* 49. 字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
解释:
在 strs 中没有字符串可以通过重新排列来形成 "bat"。
字符串 "nat" 和 "tan" 是字母异位词,因为它们可以重新排列以形成彼此。
字符串 "ate" ,"eat" 和 "tea" 是字母异位词,因为它们可以重新排列以形成彼此。*/
/*
char[] c = str.toCharArray();
Arrays.sort(c);
*/
public List<List<String>> groupAnagrams(String[] strs){
//hashmap+sort
Map<String, List<String>> hashmap = new HashMap<>();
for(String str : strs){
//stirng --> char[]sort --->string
char[] temp = str.toCharArray();
Arrays.sort(temp);
String temps = new String(temp);
if(hashmap.containsKey(temps)){
List<String> tmeplist = hashmap.get(temps);
tmeplist.add(str);
hashmap.put(temps,tmeplist);
}else{
List<String> templist = new ArrayList<>();
templist.add(str);
hashmap.put(temps,templist);
}
}
return new ArrayList<List<String>>(hashmap.values());
}
public static void main(String[] args){
lc49 solution = new lc49();
String[] test1 = {"eat", "tea", "tan", "ate", "nat", "bat"};
System.out.println("test:" + solution.groupAnagrams(test1));
}
}
128.最长连续序列
java
package hot100;
import java.util.*;
public class lc128 {
/*最长连续序列
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
* */
//注意要点:1.用set 2.在set里面遍历
public int longestConsecutive(int[] nums){
//o(n)不能排序,hash
//这个会超时
//Map<Integer,Integer> hashmap = new HashMap<>();
//用set
Set<Integer> hashset = new HashSet<>();
for(int num : nums){
hashset.add(num);
}
//存在这个的n-1吗》找到第一个数,然后有继续,更新 max?
int max = 0;
//要在set里面遍历
for(int num : hashset){
if(!hashset.contains(num-1)){
int length = 1;
int tempnum = num;
while ((hashset.contains(tempnum+1))){
length++;
tempnum++;
}
max = Math.max(max, length);
}
}
return max;
}
public static void main(String[] args){
lc128 solution = new lc128();
int[] nums = new int[]{100,4,200,1,3,2};
System.out.println("答案: "+ solution.longestConsecutive(nums));
}
}
283.移动零
java
package hot100;
import java.util.Arrays;
public class lc283 {
/* 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
*/
//模拟栈的写法
public void moveZeroes(int[] nums){
//模拟栈的写法
int stackSize = 0;
for(int num : nums){
if(num != 0){
nums[stackSize] = num;
stackSize++;
}
}
Arrays.fill(nums, stackSize, nums.length,0);
}
//左右指针的写法
public void moveZeroes2(int[] nums){
}
public static void main(String[] args) {
lc283 solution = new lc283();
int[] nums = new int[]{0,1,0,3,12};
solution.moveZeroes(nums);
for(int num : nums){
System.out.print(num + " ");
}
}
}
随机知识
题目 1:在 Java 生态中,你会如何设计 Agent 的"工具调用"(Function Calling)层,以支撑高并发场景?
考察点:Java 异步编程、JSON Schema 生成、超时隔离。
参考答案 :
在大厂高并发场景下,工具调用不能是简单的同步 HTTP 请求。我的设计会分三层:
-
Schema 注册与生成层 :利用 Java 注解(如
@Tool)和反射,在启动时生成标准的 JSON Schema。为了性能,我会使用 GraalVM Native Image 提前编译这部分,或使用Jackson配合缓存避免每次调用都重新解析类结构。 -
异步非阻塞执行层 :Agent 一次请求可能并行调用 5-8 个工具(如同时读多个文件)。我会利用 Spring WebFlux 或 Java 21 虚拟线程(Virtual Threads) 包装工具逻辑。对于外部 I/O 工具,必须设置严格的 超时阈值(Timeout) 和 熔断器(Resilience4j),防止单个工具卡死导致整个 Agent 循环超时(Gateway Timeout)。
-
结果流式回传 :工具执行结果不等待全部完成再返回,而是通过 SSE(Server-Sent Events) 流式推送给前端,提升用户体验。
题目 2:Agent 的"记忆"(Memory)在分布式微服务架构中如何设计?请给出 Java 实现方案。
考察点:分布式缓存、序列化、向量检索。
参考答案 :
Agent 的记忆分为短期(会话上下文)和长期(向量库)。在大厂,服务是无状态的,因此记忆必须外置:
-
短期记忆(Short-term) :使用 Redis + 滑动窗口存储。Key 为
session_id,Value 为压缩后的对话列表。由于 LLM Token 有限,我会在 Java 服务中启动一个后台线程 ,利用tiktoken-java库实时计算 Token 数,当超过阈值(如 Context Window 的 70%)时,触发 Summarizer (调用小模型)进行历史摘要压缩,并用Lua 脚本保证原子性更新。 -
长期记忆(Long-term / RAG) :使用 RedisSearch 或 Elasticsearch 向量索引。Java 服务通过 Spring AI 的
VectorStore接口接入。关键优化点是 内存对齐 :将高频访问的文档片段使用Caffeine本地缓存预热,减少网络 I/O。
题目 3:Agent 容易产生"幻觉"并执行危险的 Shell 命令或删除文件。在 Java 后端,你如何构建"护栏"(Guardrails)来兜底?
考察点:安全防护、路径穿越防御、正则/语义拦截。
参考答案 :
这是决定 Agent 能否上生产的核心。我有三层护栏策略:
-
路径沙箱(Path Sandbox) :Java 后端维护一个
WorkspaceContext,所有文件读写必须基于根目录。我会重写 Java 的FileAPI,在工具层前置一个 PathValidator ,利用java.nio.file.Path.normalize()检查路径是否包含..,强行拦截跳出工作区的操作。 -
危险命令语义拦截 :对于
run_shell工具,不直接交给 Bash 执行。我会先用 Antlr4 或正则表达式解析命令 AST,匹配高危指令(rm -rf、chmod 777、:(){ :|:& };:等)。匹配到危险指令时,不报错,而是强制转为AskUser模式,通过 WebSocket 推送给前端,等人工审批通过后才放行。 -
循环熔断 :维护一个
ConcurrentHashMap记录工具调用指纹,如果同一工具连续失败或返回相同结果超过 3 次,直接抛出AgentStuckException终止循环。
题目 4:在大厂,一个 Agent 任务可能需要运行几分钟。当 Java 服务发布重启时,如何实现 Agent 的无损恢复(断点续传)?
考察点:状态机设计、Checkpoint 机制、序列化。
参考答案 :
我们不可能让用户因为重启重跑,必须引入 Checkpoint(检查点)。
-
状态快照设计 :在 Java 中定义一个
AgentState对象,包含current_step_index、pending_tool_calls、compressed_memory。利用 Protobuf 进行序列化(比 JSON 更小更快)。 -
持久化策略 :每次 Agent 调用关键工具前,都会将
AgentState异步写入 RocksDB (本地盘)或 S3 。写入使用 Double Buffer 技术,确保写操作不阻塞主循环。 -
恢复流程 :服务启动时,拦截用户请求,检查是否存在
run_id对应的 Checkpoint。如果存在,使用 Java Kryo 反序列化还原对象,跳过已完成的步骤。关键在于 幂等性设计:需要将每个工具执行的结果存入状态中,恢复时重放日志,确保 Shell 命令不会因为重启被执行两次。
题目 5:在多 Agent 协作(Multi-Agent)系统中,Java 如何解决子 Agent 上下文污染和死锁问题?
考察点:线程模型、Actor 模式、上下文隔离。
参考答案 :
顶级大厂复杂的任务往往需要主 Agent 派发子 Agent(如代码审查员、测试员)。我会基于 Akka(Actor 模型) 或 Spring 的 @Async + 隔离的 ClassLoader 构建。
-
上下文污染(Context Pollution) :每个子 Agent 拥有独立的
ContextManager实例。主 Agent 给子 Agent 下任务时,传递的是只读的上下文指针 ,子 Agent 产生的工具调用结果写入自己的私有上下文。任务完成后,只将最终结论(Summary)回调给主 Agent,绝不允许子 Agent 修改主 Agent 的完整历史记录。 -
死锁/循环依赖(Deadlock) :设置 TTL(任务存活时间) 。同时,在 Java 层维护一个有向无环图(DAG)依赖表。如果检测到子 Agent A 要调用子 Agent B,且 B 正在等待 A 的结果,立即中断并回滚。使用
CompletableFuture.orTimeout()强制超时释放线程资源。
碎碎念:后续会更新每天学习的八股和算法 题,开始准备秋招的第62/63天。努力连续更新100天!以后每天就按,秋招项目【java +agent】,科研,必做项目,算法,八股,锻炼身体来总结。
总结:比起之前放假完全不学习,这周还是进步一点点
1.hot100 【acm】 5/100 ,确实自己在idea里面只看题目写和测试,还是有点不太一样的
2.秋招项目,【java 项目】,
【agent 项目 】,2h
3.科研。确定方向就搞就可以了
4.实习;
6.背八股,
7.锻炼身体,
冲冲冲!遇到困难动脑子,你的价值就是解决问题的能力