Browse Source

rotate image

Zhang Li 2 years ago
parent
commit
e00174529d
2 changed files with 140 additions and 0 deletions
  1. 1 0
      src/solutions/other/mod.rs
  2. 139 0
      src/solutions/other/rotate_image.rs

+ 1 - 0
src/solutions/other/mod.rs

@@ -1 +1,2 @@
 mod divide_two_integers;
+mod rotate_image;

+ 139 - 0
src/solutions/other/rotate_image.rs

@@ -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);
+    }
+}