|
@@ -0,0 +1,139 @@
|
|
|
+struct Solution;
|
|
|
+
|
|
|
+impl Solution {
|
|
|
+ pub fn rotate(matrix: &mut Vec<Vec<i32>>) {
|
|
|
+ let n = matrix.len();
|
|
|
+
|
|
|
+ let mut step = n as i32 - 1;
|
|
|
+ let mut round = 0;
|
|
|
+ let mut tmp = 0;
|
|
|
+ while step > 0 {
|
|
|
+ let i = 0;
|
|
|
+ for j in 0..step as usize {
|
|
|
+ // i, j 是0,0坐标系
|
|
|
+ let (mut ii, mut jj) = (i, j);
|
|
|
+ for k in 0..4 {
|
|
|
+ let r = Self::get_rotate_vec(k);
|
|
|
+ let (ni, nj) = Self::rotate_idx(ii, jj, step as usize, r);
|
|
|
+ // 返回真实的坐标
|
|
|
+ let (ni_idx, nj_idx) = Self::convert_back(ni, nj, round);
|
|
|
+ let (ii_idx, jj_idx) = Self::convert_back(ii, jj, round);
|
|
|
+ if k == 0 {
|
|
|
+ tmp = matrix[ii_idx][jj_idx];
|
|
|
+ }
|
|
|
+ let _t = matrix[ni_idx][nj_idx];
|
|
|
+ matrix[ni_idx][nj_idx] = tmp;
|
|
|
+ tmp = _t;
|
|
|
+ ii = ni;
|
|
|
+ jj = nj;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ round += 1;
|
|
|
+ step = n as i32 - 2 * round as i32 - 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fn get_rotate_vec(idx: usize) -> (i32, i32, i32) {
|
|
|
+ // (inc_x, inc_y, inc_x | inc_y first)
|
|
|
+ match idx {
|
|
|
+ 0 => (1, 1, 1),
|
|
|
+ 1 => (1, -1, 0),
|
|
|
+ 2 => (1, -1, 1),
|
|
|
+ 3 => (-1, 1, 0),
|
|
|
+ _ => unreachable!(),
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fn convert_back(i: usize, j: usize, round: usize) -> (usize, usize) {
|
|
|
+ (i + round, j + round)
|
|
|
+ }
|
|
|
+
|
|
|
+ fn rotate_idx(i: usize, j: usize, step: usize, r: (i32, i32, i32)) -> (usize, usize) {
|
|
|
+ let i = i as i32;
|
|
|
+ let j = j as i32;
|
|
|
+ let step = step as i32;
|
|
|
+ let (r1, r2) = match r {
|
|
|
+ (1, 1, 1) => {
|
|
|
+ // (0, 2) => (2, 3) step: 3
|
|
|
+ if j != 0 {
|
|
|
+ ((j + i) as usize, step as usize)
|
|
|
+ } else {
|
|
|
+ (i as usize, step as usize)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ (1, -1, 0) => {
|
|
|
+ // (2, 3) => (3, 1) step: 3
|
|
|
+ if i != 0 {
|
|
|
+ (step as usize, (j - i) as usize)
|
|
|
+ } else {
|
|
|
+ (step as usize, j as usize)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ (1, -1, 1) => {
|
|
|
+ // (3, 1) => (1, 0) step: 3
|
|
|
+ if j != step {
|
|
|
+ ((i - (step - j)) as usize, 0)
|
|
|
+ } else {
|
|
|
+ (i as usize, 0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ (-1, 1, 0) => {
|
|
|
+ // (1, 0) => (0, 2) step: 3
|
|
|
+ if i != step {
|
|
|
+ (0, (j + (step - i)) as usize)
|
|
|
+ } else {
|
|
|
+ (0, j as usize)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ _ => unreachable!(),
|
|
|
+ };
|
|
|
+ (r1, r2)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[cfg(test)]
|
|
|
+mod tests {
|
|
|
+ use super::*;
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_rotate_idx() {
|
|
|
+ assert_eq!(Solution::rotate_idx(0, 2, 3, (1, 1, 1)), (2, 3));
|
|
|
+ assert_eq!(Solution::rotate_idx(2, 3, 3, (1, -1, 0)), (3, 1));
|
|
|
+ assert_eq!(Solution::rotate_idx(3, 1, 3, (1, -1, 1)), (1, 0));
|
|
|
+ assert_eq!(Solution::rotate_idx(1, 0, 3, (-1, 1, 0)), (0, 2));
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_rotate_idx_1() {
|
|
|
+ assert_eq!(Solution::rotate_idx(0, 0, 3, (1, 1, 1)), (0, 3));
|
|
|
+ assert_eq!(Solution::rotate_idx(0, 3, 3, (1, -1, 0)), (3, 3));
|
|
|
+ assert_eq!(Solution::rotate_idx(3, 3, 3, (1, -1, 1)), (3, 0));
|
|
|
+ assert_eq!(Solution::rotate_idx(3, 0, 3, (-1, 1, 0)), (0, 0));
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_case_1() {
|
|
|
+ let mut matrix = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
|
|
|
+ Solution::rotate(&mut matrix);
|
|
|
+ let expect = vec![vec![7, 4, 1], vec![8, 5, 2], vec![9, 6, 3]];
|
|
|
+ assert_eq!(matrix, expect);
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_case_2() {
|
|
|
+ let mut matrix = vec![
|
|
|
+ vec![5, 1, 9, 11],
|
|
|
+ vec![2, 4, 8, 10],
|
|
|
+ vec![13, 3, 6, 7],
|
|
|
+ vec![15, 14, 12, 16],
|
|
|
+ ];
|
|
|
+ Solution::rotate(&mut matrix);
|
|
|
+ let expect = vec![
|
|
|
+ vec![15, 13, 2, 5],
|
|
|
+ vec![14, 3, 4, 1],
|
|
|
+ vec![12, 6, 8, 9],
|
|
|
+ vec![16, 7, 10, 11],
|
|
|
+ ];
|
|
|
+ assert_eq!(matrix, expect);
|
|
|
+ }
|
|
|
+}
|