每周完成一个 ARTS: 至少做一个 leetcode 的算法题、阅读并点评至少一篇英文技术文章、学习至少一个技术技巧、分享一篇有观点和思考的技术文章。(也就是 Algorithm、Review、Tips、Share 简称 ARTS)
算法:https://leetcode.cn/problems/decode-string/?envType=study-plan-v2&envId=selected-coding-interview

我目前想到的思路。遍历字符串,数字、[、字母依次压栈,遇到 ] 时往回 pop 到 [,取出前面的数字,重复拼接后压回栈。嵌套括号也能自然处理,因为内层展开后压回栈,外层再 pop 时拿到的就是已经展开好的字符串。
需要注意(踩过的 3 个坑):
1、重复次数:pop 出来的 values 里已经有一份了,循环应该从 j=0 到 j < nums-1,否则会多重复一次
2、不能用 `reverse()` 处理 pop 顺序:栈里有些元素是之前展开过的多字符字符串(比如 "jkjk"),如果先 append 再对整个 values 做 reverse(),会把多字符元素内部顺序也反转掉。正确做法是 pop 的时候直接用 insert(0, stacks.pop()) 保持正确顺序
3、最终拼接用 `append` 不是 `insert(0,...)`:Java 的 Stack for-each 从底到顶遍历,用 append 才是正序拼接
代码:
public String decodeString(String s) {
if (s.isEmpty()) {
return "";
}
char[] chars = s.toCharArray();
Stack<String> stacks = new Stack<>();
StringBuilder num = new StringBuilder();
for (char c : chars) {
if (Character.isDigit(c)) {
num.append(c);
} else if (c == '[') {
if (num.length() > 0) {
stacks.push(num.toString());
num = new StringBuilder();
}
stacks.push(String.valueOf(c));
} else if (c == ']') {
StringBuilder values = new StringBuilder();
while (!stacks.isEmpty() && !"[".equals(stacks.peek())) {
values.insert(0, stacks.pop());
}
// 单独拿出来 [
stacks.pop();
int nums = Integer.parseInt(stacks.pop());
String coreStr = values.toString();
for (int j = 0; j < nums - 1; j++) {
values.append(coreStr);
}
stacks.push(values.toString());
} else {
stacks.push(String.valueOf(c));
}
}
StringBuilder result = new StringBuilder();
for (String str : stacks) {
result.append(str);
}
return result.toString();
}文章:https://nesbitt.io/2026/09/24/package-manager-sandboxing.html
Andrew Nesbitt(Homebrew 维护者)对各包管理器沙箱机制做了一次全面调查。文章核心观点是:包管理器沙箱和 AI 编码 Agent 沙箱本质上是同一个问题,都需要执行未经审查的第三方代码,都收敛到了同一组 OS 原语(macOS 的 Seatbelt、Linux 的 Landlock/namespace),甚至在实际场景中互相嵌套运行(Homebrew 专门处理了"在 Agent 沙箱里运行 brew"的情况)。
几个关键发现:
install.ps1;Homebrew 的 *_steps 把任意 Ruby 钩子替换为签名的声明式数据最让人印象深刻的一个数据:Anthropic 报告用户对 Claude Code 权限弹窗的批准率高达 93% —— 这就是为什么"每次都问用户"行不通,必须走沙箱路线。真正使用的时候,都是不看内容,直接无脑点击同意的,我就是这样😂
Agent 具备自主安装依赖的能力 + 包管理器缺乏沙箱 = 供应链攻击的绝佳放大器。Shai-Hulud 蠕虫通过 npm postinstall 传播后,居然还能把 hook 写入 Claude Code 的配置文件实现持久化,这说明 Agent 和包管理器的安全边界必须协同设计,而不是各管各的。
最近没啥 Tips 推荐一些 mac 软件吧:
1、Stats:展示状态
2、OpenUsage:查看 Cursor、Claude、Codex 等等的使用额度、充值时间等等,这里不推荐 OpenClaw 之父的 CodexBar,他运行一段时间磁盘的读取量非常夸张,个人强烈不推荐,下面是官方的演示图片:

3、EcoPaste:剪切板,如果有一些问题可以让 AI 修复之后继续使用,免费开源的 yyds
文章:https://www.privatemode.ai/blog/system-one-from-glm-flash(虽然有点广子,但是还有有东西的)
Privatemode AI 这篇文章演示了一个非常巧妙的技巧:如何把普通的开源 LLM(GLM-5.3-Flash)变成一个类似 TypeSafe AI Jev 的 "System One" 决策模型。
背景:TypeSafe AI 最近发布了 Jev,一个专为结构化决策设计的非自回归模型。它不像传统 LLM 那样逐 token 生成文本,而是在单次前向传播中直接输出决策结果和校准过的置信概率,号称比前沿 LLM 快 ~200x、便宜 ~400x。但 Jev 是闭源的。
核心技巧:这篇文章展示了如何用开源模型复刻这个能力,关键就是 vLLM 的 allowed_token_ids 参数。
`allowed_token_ids` 是什么? 它是 vLLM SamplingParams 中的一个参数,作用是在采样阶段对 logits 做 masking:把不在列表里的所有 token 的概率被严格限制为 0,保证绝对不会被生成 ,强制模型只能从你指定的 token 中选择输出。这意味着模型在一次前向传播中,会把所有概率质量分配给你允许的那几个 token。
怎么用? 举一个情感分类的例子:
from vllm import LLM, SamplingParams
import math
llm = LLM(model="zai-org/glm-4-9b-chat-1m")
tokenizer = llm.get_tokenizer()
# 定义标签 → 获取对应的 token ID
labels = ["0", "1", "2"] # 0=正面, 1=负面, 2=中性
allowed_ids = [tokenizer.encode(l)[0] for l in labels]
params = SamplingParams(
max_tokens=1, # 只输出一个 token
allowed_token_ids=allowed_ids,
logprobs=len(labels), # 获取所有候选的 logprob
temperature=0, # 确定性输出
)
prompt = "判断以下评论的情感倾向(0=正面/1=负面/2=中性):'这个产品太好用了!'\n答案:"
outputs = llm.generate([prompt], params)
# 读取结果
token = outputs[0].outputs[0].text
logprob = outputs[0].outputs[0].logprobs[0][int(outputs[0].outputs[0].token_ids[0])].logprob
confidence = math.exp(logprob) # e^logprob = 概率
print(f"分类: {token}, 置信度: {confidence:.2%}")
# 输出: 分类: 0, 置信度: 94.32%几个关键细节:
logprob=0.0 表示 100% 置信 e^0=1,越负越不确定。通过 math.exp(logprob) 可以直接得到概率值guided_decoding(JSON schema 约束),但那是在多 token 生成中逐步约束,仍然是自回归的。allowed_token_ids + max_tokens=1 才是真正的"单次前向传播"那么折腾了半天和原版的 Jev 有啥区别?这个 「Jev」可以做到图像做分类决策、可以更换更强的开源模型做决策等等
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。