news 2026/9/30 11:25:45

元宝 LeetCode 131. 分割回文串 Rust实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
元宝 LeetCode 131. 分割回文串 Rust实现

Rust 实现 LeetCode 131 的核心逻辑和 Python 完全一致,依然是回溯(Backtracking)。不过在 Rust 里需要稍微注意字符串处理和递归函数的写法。

方法一:回溯 + 实时回文判断(最直观,面试首选)AC

Rust 的
“String” 是 UTF-8 编码,按索引切片不太方便,但本题输入保证是小写英文字母,所以可以直接用
“as_bytes()” 转成字节切片来处理,回文判断用双指针更高效。

impl Solution {
pub fn partition(s: String) -> Vec<Vec> {
let bytes = s.as_bytes();
let mut res = Vec::new();
let mut path = Vec::new();
backtrack(0, bytes, &mut path, &mut res);
res
}
}

fn backtrack(
start: usize,
bytes: &[u8],
path: &mut Vec,
res: &mut Vec<Vec>,
) {
// 切到末尾,说明找到了一种合法分割
if start == bytes.len() {
res.push(path.clone()); // 注意:必须 clone,不能直接移走
return;
}

// 枚举当前起点能切出的所有子串 for end in start..bytes.len() { if is_palindrome(&bytes[start..=end]) { // 转成 String 加入路径 let sub = String::from_utf8(bytes[start..=end].to_vec()).unwrap(); path.push(sub); // 做选择 backtrack(end + 1, bytes, path, res); // 递归切后面的 path.pop(); // 撤销选择(回溯) } }

}

fn is_palindrome(bytes: &[u8]) -> bool {
let (mut i, mut j) = (0, bytes.len().saturating_sub(1));
while i < j {
if bytes[i] != bytes[j] {
return false;
}
i += 1;
if j > 0 {
j -= 1;
} else {
break;
}
}
true
}

方法二:回溯 + DP 预处理回文表(性能更优)

如果字符串较长,频繁切片判断回文会有开销。可以先 DP 预处理所有子串的回文状态,回溯时 O(1) 查询。

impl Solution {
pub fn partition(s: String) -> Vec<Vec> {
let bytes = s.as_bytes();
let n = bytes.len();

// 1. 预处理:dp[i][j] 表示 bytes[i..=j] 是否为回文 let mut dp = vec![vec![false; n]; n]; for i in 0..n { for j in i..n { if bytes[i] == bytes[j] && (j - i <= 2 || dp[i + 1][j - 1]) { dp[i][j] = true; } } } // 2. 回溯 let mut res = Vec::new(); let mut path = Vec::new(); backtrack(0, bytes, &dp, &mut path, &mut res); res }

}

fn backtrack(
start: usize,
bytes: &[u8],
dp: &[Vec],
path: &mut Vec,
res: &mut Vec<Vec>,
) {
if start == bytes.len() {
res.push(path.clone());
return;
}

for end in start..bytes.len() { if dp[start][end] { let sub = String::from_utf8(bytes[start..=end].to_vec()).unwrap(); path.push(sub); backtrack(end + 1, bytes, dp, path, res); path.pop(); } }

}

Rust 版特有注意事项(面试常问)

要点 说明

“path.clone()”
“res.push(path)” 会移动所有权导致后续无法回溯,必须
“clone”,和 Python 里
“path[:]” 一个道理
字符串转换
“&[u8]” 转
“String” 用
“String::from_utf8(…).unwrap()”,本题输入安全不会 panic
递归函数位置 Rust 闭包不能递归调用自己,所以写成独立的
“fn backtrack”(或放在
“impl” 里作为辅助方法)
切片索引
“bytes[start…=end]” 是闭区间,对应
“s[start:end+1]”(Python 风格)

“saturating_sub” 回文判断里
“j = bytes.len() - 1” 在空切片时会溢出,用
“saturating_sub(1)” 更安全(虽然本题
“n >= 1”)

复杂度分析

和 Python 版一致:

  • 时间复杂度:最坏
    “O(2ⁿ · n)”(全
    “‘a’” 字符串,每种切法都合法,拷贝路径耗时
    “O(n)”)
  • 空间复杂度:
    “O(n)” 递归栈深度(不计结果存储);DP 版额外
    “O(n²)” 存储回文表

跑个示例

let s = “aab”.to_string();
let res = Solution::partition(s);
// res = [[“a”,“a”,“b”], [“aa”,“b”]]

要不要我顺便给你写一下 LeetCode 132(分割回文串 II) 的 Rust DP 实现?那题求最少分割次数,从回溯直接升级到动态规划,是这道题目的经典进阶。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 11:20:19

Python学习笔记——字符串

#!/usr/bin/python # Write Python 3 code in this online editor and run it. s1 hello word print(type(s1)) print(s1) #字符串中的每个字符都有一个位置编号&#xff0c;从 0 开始正向编号&#xff0c;或从 -1 开始反向编号。 print(s1[-3])s2 """Im a st…

作者头像 李华
网站建设 2026/9/30 11:19:46

专科实训毕业论文写作:我使用ai写作工具的个人体会

**免责声明&#xff1a;本文仅为本人写作过程中的个人体验记录与思考&#xff0c;不存在任何产品推荐或者商业推广意图。AI工具只适合用来做思路启发、行文梳理。毕业论文全部内容、实训分析都要求学生本人独立完成&#xff0c;请严格遵从本校毕业设计的学术规范。 最近在完成自…

作者头像 李华
网站建设 2026/9/30 11:17:22

Apache POI设置Word页面尺寸与边距实战

最近在搞一个 Java 后端导出 Word 文档的功能&#xff0c;需求清单里明明白白写着&#xff1a;默认 A4 纸、上下边距 2.54 厘米、左右边距 3.18 厘米。刚开始我寻思这不就是页面设置嘛&#xff0c;Word 里点两下的事。但换到用 Apache POI 5.2.2 在代码里操作&#xff0c;水就深…

作者头像 李华
网站建设 2026/9/30 11:13:08

Unity多人联机架构实战:Orleans+SuperSocket+Redis+MongoDB搭建详解

聊实时项目的时候&#xff0c;服务端选型永远是个绕不开的大问题。我最近在项目里刚落地一套架构&#xff1a;Unity客户端负责表现和交互&#xff0c;Orleans服务端扛业务逻辑与有状态actor&#xff0c;SuperSocket做TCP长连接网关&#xff0c;Redis处理缓存和分布式协作&#…

作者头像 李华