topcode【随机算法题】【2026.5.13打卡-java版本】
151.反转字符串中的单词
示例 1:
输入:s = "the sky is blue" 输出:"blue is sky the"
要点: 1.以 ’ ‘ 分割string,然后stringbuild.append()得到单词 2..队列【offerFirst】
3.string.join(" ", ans)【队列转换为字符串】
class Solution {
public String reverseWords(String s) {
//队列的方法
//1.去头去尾“ ”
//2.stringbuild+队列
//3.细节处理的队列——》string的转换,String.join(" ", ans);
int left = 0;
int right = s.length() -1;
while(s.length() >= 0 && s.charAt(left) == ' '){
left++;
}
while(s.length() >= 0 && s.charAt(right) == ' '){
right--;
}
StringBuilder word = new StringBuilder();
//StringBuilder ans = new StringBuilder();
Deque<String> ans = new ArrayDeque<>();
while(left <= right){
char c = s.charAt(left);
if(word.length() != 0 && c == ' '){
ans.offerFirst(word.toString());
word = new StringBuilder();
}else if(c != ' '){
word.append(c);
}
left++;
}
if(word.length() > 0){
ans.offerFirst(word.toString());
}
return String.join(" ", ans);
}
}
78.子集
示例 1:
输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
要点:回溯, backtrack(start,ans,path,nums),夹心饼干【add, backtrak,remove】
class Solution {
/* 回溯的图
[]
/ \
[1] [2] [3] ← 第一层选择(i=0,1,2)
/ \ \
[1,2] [1,3] [2,3] ← 第二层选择
/
[1,2,3] ← 第三层选择
*/
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
backtrack(0, nums, new ArrayList(), ans);
return ans;
}
public void backtrack(int start, int[] nums, List<Integer> path, List<List<Integer>> ans){
// ans.add(path);
//加新的点
ans.add(new ArrayList<>(path));
for(int i = start; i < nums.length; i++){
path.add(nums[i]);
backtrack(i+1, nums, path, ans);
path.remove(path.size() - 1);
}
}
}
46.全排列
要点,回溯:backtrack(used,ans,path,nums),夹心饼干【add,uese【ture】, backtrak,used【fasle】,remove】
class Solution {
public List<List<Integer>> permute(int[] nums) {
//回溯
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
boolean[] used = new boolean[nums.length];
int n = nums.length;
backtrack(nums, used, path, ans);
return ans;
}
public void backtrack(int[] nums, boolean[] used, List<Integer> path, List<List<Integer>> ans){
if(path.size() == nums.length){
List<Integer> temp = new ArrayList<>(path);
ans.add(temp);
return;
}
for(int i = 0; i < nums.length; i++){
if(used[i]){
continue;
}else{
path.add(nums[i]);
used[i] = true;
backtrack(nums, used, path, ans);
used[i] = false;
path.remove(path.size() - 1);
}
}
}
}
随机知识
LangChain与LangGraph
关于LangChain与LangGraph的区别,一个普遍的误解是认为它们是二选一的竞争关系。事实上,两者出自同一个团队,更像是一套渐进式的技术栈:LangChain是快速构建LLM应用的组件库,而LangGraph则是用于编排复杂、有状态智能体工作流的引擎。
LangChain和LangGraph的基本使用方法
要真正掌握LangChain和LangGraph,关键在于理解它们提供的API接口(也就是“方法”)。前者通过组件将你的指令传给LLM,后者则负责编排整个任务的流程。
🧩 LangChain:组件的核心方法
LangChain的核心在于其丰富的“组件”,每个组件都通过特定的方法与你的程序进行交互。
1. 模型交互与提示管理
| 核心方法 / 组件 | 主要用途 | 代码示例 (片段) |
|---|---|---|
ChatOpenAI (聊天模型) |
初始化并连接到特定的聊天模型(如GPT)。 | model = ChatOpenAI(model="gpt-4o-mini") |
.bind_tools(tools) |
将一组工具“绑定”到模型,赋予其调用外部功能(如搜索引擎、计算器)的能力。 | model_with_tools = model.bind_tools(tools) |
PromptTemplate (提示模板) |
创建一个可复用的提示词模板,支持动态变量插值。 | prompt = PromptTemplate.from_template(...) |
.from_messages() |
从消息列表中创建聊天提示模板,常用于定义系统、用户和AI的角色。 | ChatPromptTemplate.from_messages([...]) |
2. LCEL与Runnable协议
这是现代LangChain推荐的工作方式,通过管道符(|)和Runnable接口,将组件串联成清晰的工作流。
| 核心方法 / 组件 | 主要用途 | 代码示例 (片段) |
|---|---|---|
| (管道操作符) |
将多个Runnable组件串联起来,前一个的输出是后一个的输入。 |
chain = prompt \| model \| output_parser |
.invoke(input) |
同步执行整个链,是触发一次完整调用的最常用方法。 | response = chain.invoke({"city": "Paris"}) |
.batch(inputs) |
对一个输入列表批量执行,用于并行处理多个请求以提高效率。 | responses = chain.batch([{"city": "NY"}, {"city": "LA"}]) |
| RunnablePassthrough | 在链中透传数据,或在传递前对数据进行预处理,如添加或修改字段。 | RunnablePassthrough.assign(new_field=...) |
| RunnableParallel | 用于并行执行多个任务(如同时查询天气和新闻),合并结果后再进行下一步。 | RunnableParallel(weather=chain1, news=chain2) |
| RunnableBranch | 根据输入数据执行条件路由,类似编程中的if/elif/else语句,用于实现分支逻辑。 |
RunnableBranch((condition1, chain1), default_chain) |
3. 工具定义与调用 (Tool/Function Calling)
这是让LLM“动”起来的关键,使其能与外部世界交互。
| 核心方法 / 组件 | 主要用途 | 代码示例 (片段) |
|---|---|---|
@tool 装饰器 |
将任何Python函数快速声明为工具,LLM会读取函数的docstring来理解其用途。 | @tool def get_weather(city: str) -> str: |
BaseTool 类 |
所有工具的抽象基类。当需要更复杂的工具逻辑时,可以通过继承此类来创建。 | class MyComplexTool(BaseTool): |
ToolCall |
LLM返回的“工具调用请求”对象,包含了工具名和参数,我们需要解析它来执行实际函数。 | tool_call = response.tool_calls[0] |
StructuredTool |
用于创建具有结构化的、预定义模式(如Pydantic模型)的多参数工具的基类。 | StructuredTool.from_function(...) |
🌐 LangGraph:编排的核心方法
LangGraph的全部工作都围绕“状态图”(StateGraph)展开,通过节点和边来定义智能体的复杂工作流。
| 核心方法 / 组件 | 主要用途 | 代码示例 (片段) |
|---|---|---|
StateGraph(state_schema) |
构建器的构造函数。参数state_schema定义了图的数据结构(TypedDict或Pydantic模型)。 |
graph = StateGraph(MyState) |
graph.add_node(name, func) |
向图中添加一个节点,func是实际业务逻辑(如模型调用、工具调用)。 |
graph.add_node("agent", agent_node) |
graph.add_edge(source, target) |
在节点间添加一条固定的、无条件的边。 | graph.add_edge("start", "agent") |
graph.add_conditional_edges() |
添加条件边,根据函数返回值动态决定下一步走向,是构建循环和分支的核心。 | graph.add_conditional_edges("agent", router) |
graph.set_entry_point(key) |
设置图的起始节点。 | graph.set_entry_point("agent") |
graph.compile() |
编译构建器,生成一个可执行的、不可变的CompiledGraph对象。 |
app = graph.compile() |
.invoke(input_dict) |
执行编译后的图并等待最终状态,适用于批处理任务。 | final_state = app.invoke({"input": "..."}) |
.stream(input_dict) |
流式地执行图,可以在每个节点完成后实时获取状态更新,适合构建聊天应用。 | for output in app.stream(...): print(output) |
state.update() |
在节点函数内部,通过返回一个字典来更新图的全局状态。特殊的Reducer用于处理并发更新冲突。 |
return {"messages": [new_message]} |
ToolNode |
LangGraph预置的工具节点,负责解析模型输出的工具调用请求并执行,自动化了工具调用循环。 | tool_node = ToolNode(tools) |
Command |
组合状态更新与路由控制。允许节点在执行逻辑后,直接指定下一个要跳转的节点,实现更精细的控制。 | return Command(goto="other_node", update={...}) |
Send |
用于实现Map-Reduce模式,动态地向一个目标节点发送多个任务,实现并行处理。 | Send("worker_node", {"task": task_data}) |
💎 总结:从"学会"到"会用"
-
起步:从LangChain的线性链开始
刚入门时,最常用的就是prompt | model | output_parser这个经典三件套。通过.invoke()方法运行它,你就能快速实现文本总结、翻译等任务。这能让你最快地跑通第一个AI应用。 -
进阶:引入LangGraph的循环与状态
当你需要构建一个能根据前一步结果“思考”的智能体时,就到了LangGraph发挥作用的时候。它的核心套路是:- 定义状态:创建一个
TypedDict类,明确哪些数据需要在图中流转。 - 构建图:使用
StateGraph(YourState),然后通过.add_node()添加模型调用和工具执行节点。 - 实现循环:关键在于
.add_conditional_edges()方法。通过它,你可以判断模型是否返回了工具调用,从而将流程导向工具节点,并在工具执行后自动回到模型节点,形成一个ReAct(思考-行动-观察)循环。 - 完成流程:使用
.set_entry_point()和graph.compile()完成图的构建。
python伪代码示例from langgraph.graph import StateGraph, END定义状态...class AgentState(TypedDict):messages: list定义节点函数...workflow = StateGraph(AgentState)workflow.add_node("agent", call_model)workflow.add_node("action", execute_tool)workflow.set_entry_point("agent")关键:根据条件建立循环workflow.add_conditional_edges("agent", should_act, {"yes": "action", "no": END})workflow.add_edge("action", "agent") # 工具执行后,总会回到agent思考app = workflow.compile() - 定义状态:创建一个
希望这份对两个库常用方法的梳理,能帮你更好地驾驭它们。如果想深入了解某个特定方法,可以随时再问我。
碎碎念:后续会更新每天学习的八股和算法题,暑假实习找不到了,开始准备秋招的第3天。努力连续更新100天!今天主要是把agent项目跑起来,还是得学习agent知识呀这年头。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)