From 68379b2b2f093dd7c07b9b77559d5829d881fdd4 Mon Sep 17 00:00:00 2001 From: Michael Xu Date: Mon, 3 Jul 2023 00:08:18 +0800 Subject: [PATCH] feat: Add rust implementation to NO.0304 --- .../README.md | 62 ++++++++++++++ .../README_EN.md | 80 ++++++++++++++++++- .../Solution.rs | 57 +++++++++++++ 3 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 solution/0300-0399/0304.Range Sum Query 2D - Immutable/Solution.rs diff --git a/solution/0300-0399/0304.Range Sum Query 2D - Immutable/README.md b/solution/0300-0399/0304.Range Sum Query 2D - Immutable/README.md index 3ed2fca47c77c..a120cfd762dd7 100644 --- a/solution/0300-0399/0304.Range Sum Query 2D - Immutable/README.md +++ b/solution/0300-0399/0304.Range Sum Query 2D - Immutable/README.md @@ -165,6 +165,68 @@ public: */ ``` +### **Rust** + +```rust +/** + * Your NumMatrix object will be instantiated and called as such: + * let obj = NumMatrix::new(matrix); + * let ret_1: i32 = obj.sum_region(row1, col1, row2, col2); + */ + +struct NumMatrix { + // Of size (N + 1) * (M + 1) + prefix_vec: Vec>, + n: usize, + m: usize, + is_initialized: bool, + ref_vec: Vec>, +} + + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl NumMatrix { + + fn new(matrix: Vec>) -> Self { + NumMatrix { + prefix_vec: vec![vec![0; matrix[0].len() + 1]; matrix.len() + 1], + n: matrix.len(), + m: matrix[0].len(), + is_initialized: false, + ref_vec: matrix, + } + } + + fn sum_region(&mut self, row1: i32, col1: i32, row2: i32, col2: i32) -> i32 { + if !self.is_initialized { + self.initialize_prefix_vec(); + } + // Since i32 will let `rustc` complain, just make it happy + let row1: usize = row1 as usize; + let col1: usize = col1 as usize; + let row2: usize = row2 as usize; + let col2: usize = col2 as usize; + // Return the value in O(1) + self.prefix_vec[row2 + 1][col2 + 1] - self.prefix_vec[row2 + 1][col1] + - self.prefix_vec[row1][col2 + 1] + self.prefix_vec[row1][col1] + } + + fn initialize_prefix_vec(&mut self) { + // Initialize the prefix sum vector + for i in 0..self.n { + for j in 0..self.m { + self.prefix_vec[i + 1][j + 1] = + self.prefix_vec[i][j + 1] + self.prefix_vec[i + 1][j] - self.prefix_vec[i][j] + self.ref_vec[i][j]; + } + } + self.is_initialized = true; + } +} +``` + ### **Go** ```go diff --git a/solution/0300-0399/0304.Range Sum Query 2D - Immutable/README_EN.md b/solution/0300-0399/0304.Range Sum Query 2D - Immutable/README_EN.md index aef4597dcc14a..5fc7b8ec07a00 100644 --- a/solution/0300-0399/0304.Range Sum Query 2D - Immutable/README_EN.md +++ b/solution/0300-0399/0304.Range Sum Query 2D - Immutable/README_EN.md @@ -52,7 +52,23 @@ numMatrix.sumRegion(1, 2, 2, 4); // return 12 (i.e sum of the blue rectangle) ## Solutions -Dynamic programming - 2D preSum. +We use $s[i + 1][j + 1]$ to represent the sum of all elements in the upper-left part up to the $i$-th row and $j$-th column, where the indices $i$ and $j$ both start from $0$. + +We can derive the following prefix sum formula: + +$$ +s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + nums[i][j] +$$ + +The sum of the elements in the rectangle with $(x_1, y_1)$ and $(x_2, y_2)$ as its upper-left and bottom-right corners respectively, is: + +$$ +s[x_2 + 1][y_2 + 1] - s[x_2 + 1][y_1] - s[x_1][y_2 + 1] + s[x_1][y_1] +$$ + +We preprocess the prefix sum array $s$ in the initialization method, and directly return the result of the above formula in the query method. + +The time complexity for initialization is $O(m \times n)$, and the time complexity for query is $O(1)$. @@ -140,6 +156,68 @@ public: */ ``` +### **Rust** + +```rust +/** + * Your NumMatrix object will be instantiated and called as such: + * let obj = NumMatrix::new(matrix); + * let ret_1: i32 = obj.sum_region(row1, col1, row2, col2); + */ + + struct NumMatrix { + // Of size (N + 1) * (M + 1) + prefix_vec: Vec>, + n: usize, + m: usize, + is_initialized: bool, + ref_vec: Vec>, +} + + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl NumMatrix { + + fn new(matrix: Vec>) -> Self { + NumMatrix { + prefix_vec: vec![vec![0; matrix[0].len() + 1]; matrix.len() + 1], + n: matrix.len(), + m: matrix[0].len(), + is_initialized: false, + ref_vec: matrix, + } + } + + fn sum_region(&mut self, row1: i32, col1: i32, row2: i32, col2: i32) -> i32 { + if !self.is_initialized { + self.initialize_prefix_vec(); + } + // Since i32 will let `rustc` complain, just make it happy + let row1: usize = row1 as usize; + let col1: usize = col1 as usize; + let row2: usize = row2 as usize; + let col2: usize = col2 as usize; + // Return the value in O(1) + self.prefix_vec[row2 + 1][col2 + 1] - self.prefix_vec[row2 + 1][col1] + - self.prefix_vec[row1][col2 + 1] + self.prefix_vec[row1][col1] + } + + fn initialize_prefix_vec(&mut self) { + // Initialize the prefix sum vector + for i in 0..self.n { + for j in 0..self.m { + self.prefix_vec[i + 1][j + 1] = + self.prefix_vec[i][j + 1] + self.prefix_vec[i + 1][j] - self.prefix_vec[i][j] + self.ref_vec[i][j]; + } + } + self.is_initialized = true; + } +} +``` + ### **Go** ```go diff --git a/solution/0300-0399/0304.Range Sum Query 2D - Immutable/Solution.rs b/solution/0300-0399/0304.Range Sum Query 2D - Immutable/Solution.rs new file mode 100644 index 0000000000000..35432c4bcf797 --- /dev/null +++ b/solution/0300-0399/0304.Range Sum Query 2D - Immutable/Solution.rs @@ -0,0 +1,57 @@ +/** + * Your NumMatrix object will be instantiated and called as such: + * let obj = NumMatrix::new(matrix); + * let ret_1: i32 = obj.sum_region(row1, col1, row2, col2); + */ + + struct NumMatrix { + // Of size (N + 1) * (M + 1) + prefix_vec: Vec>, + n: usize, + m: usize, + is_initialized: bool, + ref_vec: Vec>, +} + + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl NumMatrix { + + fn new(matrix: Vec>) -> Self { + NumMatrix { + prefix_vec: vec![vec![0; matrix[0].len() + 1]; matrix.len() + 1], + n: matrix.len(), + m: matrix[0].len(), + is_initialized: false, + ref_vec: matrix, + } + } + + fn sum_region(&mut self, row1: i32, col1: i32, row2: i32, col2: i32) -> i32 { + if !self.is_initialized { + self.initialize_prefix_vec(); + } + // Since i32 will let `rustc` complain, just make it happy + let row1: usize = row1 as usize; + let col1: usize = col1 as usize; + let row2: usize = row2 as usize; + let col2: usize = col2 as usize; + // Return the value in O(1) + self.prefix_vec[row2 + 1][col2 + 1] - self.prefix_vec[row2 + 1][col1] + - self.prefix_vec[row1][col2 + 1] + self.prefix_vec[row1][col1] + } + + fn initialize_prefix_vec(&mut self) { + // Initialize the prefix sum vector + for i in 0..self.n { + for j in 0..self.m { + self.prefix_vec[i + 1][j + 1] = + self.prefix_vec[i][j + 1] + self.prefix_vec[i + 1][j] - self.prefix_vec[i][j] + self.ref_vec[i][j]; + } + } + self.is_initialized = true; + } +} \ No newline at end of file