I can't explain why your original version doesn't compile but I don't think split_first_mut
and split_last_mut
are the tools for the job. I was to simplify the implementation and make it compile by switching to remove
and pop
instead:
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
}
playground
More optimal solution, without any matrix
mutations or copies:
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
}
playground
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…