问题描述
我试图通过一一拆分顶行和底行来解决 leetcode 上的螺旋顺序问题,但我遇到了一个我无法理解的借用检查器问题。这是产生编译错误的最小示例:
pub fn f(mut matrix: &mut [Vec<i32>]) {
while let Some((_,remainder)) = matrix.split_first_mut() {
matrix = remainder;
if let Some((_,remainder)) = matrix.split_first_mut() {
matrix = remainder;
}
}
}
impl Solution {
pub fn spiral_order(mut matrix: Vec<Vec<i32>>) -> Vec<i32> {
let mut matrix = &mut matrix[..];
if matrix.is_empty() {
return Vec::new();
}
let mut ans = Vec::with_capacity(matrix.len() * matrix[0].len());
while let Some((head,tail)) = matrix.split_first_mut() {
ans.append(head);
matrix = tail;
for row in matrix.iter_mut() {
ans.push(row.pop().unwrap());
}
if let Some((head,tail)) = matrix.split_last_mut() {
matrix = tail;
ans.extend(head.into_iter().rev().map(|&mut x| x));
}
}
ans
}
}
似乎认为在循环的下一次迭代中内部借用与随后的外部借用冲突,但我认为应该没问题,因为我将余数移回矩阵,所以有一个有效的{{1}在迭代结束之前在那里。为什么编译失败,应该如何修复?
解决方法
我无法解释为什么您的原始版本无法编译,但我认为 split_first_mut
和 split_last_mut
不是这项工作的工具。我想通过切换到 remove
和 pop
来简化实现并使其编译:
fn spiral_order(mut matrix: Vec<Vec<i32>>) -> Vec<i32> {
if matrix.is_empty() {
return Vec::new();
}
let mut ans = Vec::with_capacity(matrix.len() * matrix[0].len());
while !matrix.is_empty() {
let mut head = matrix.remove(0);
ans.append(&mut head);
for row in matrix.iter_mut() {
ans.push(row.pop().unwrap());
}
if let Some(head) = matrix.pop() {
ans.extend(head.into_iter().rev());
}
}
ans
}
更优的解决方案,没有任何 matrix
突变或副本:
fn spiral_order(matrix: Vec<Vec<i32>>) -> Vec<i32> {
if matrix.len() == 0 || matrix[0].len() == 0 {
return Vec::new();
}
let mut row = 0;
let mut col = 0;
let mut up = 0;
let mut down = matrix.len() as i32 - 1;
let mut left = 0;
let mut right = matrix[0].len() as i32 - 1;
let mut dir = (0,1);
let mut ans = Vec::with_capacity(matrix.len() * matrix[0].len());
for _ in 0..(matrix.len() * matrix[0].len()) {
ans.push(matrix[row as usize][col as usize]);
match dir {
(0,1) if col == right => {
dir = (1,0);
up += 1;
}
(1,0) if row == down => {
dir = (0,-1);
right -= 1;
}
(0,-1) if col == left => {
dir = (-1,0);
down -= 1;
}
(-1,0) if row == up => {
dir = (0,1);
left += 1;
}
_ => (),}
row += dir.0;
col += dir.1;
}
ans
}