Skip to content

Commit

Permalink
Solve #307
Browse files Browse the repository at this point in the history
  • Loading branch information
aylei committed Jul 29, 2019
1 parent f8f1aa7 commit 0e10183
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,4 @@ mod n0303_range_sum_query_immutable;
mod n0304_range_sum_query_2d_immutable;
mod n1009_pancake_sorting;
mod n0306_additive_number;
mod n0307_range_sum_query_mutable;
134 changes: 134 additions & 0 deletions src/n0307_range_sum_query_mutable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**
* [307] Range Sum Query - Mutable
*
* Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
*
* The update(i, val) function modifies nums by updating the element at index i to val.
*
* Example:
*
*
* Given nums = [1, 3, 5]
*
* sumRange(0, 2) -> 9
* update(1, 2)
* sumRange(0, 2) -> 8
*
*
* Note:
*
* <ol>
* The array is only modifiable by the update function.
* You may assume the number of calls to update and sumRange function is distributed evenly.
* </ol>
*
*/
pub struct Solution {}

// Segement Tree
//
// N[0:6]
// / \
// / \
// N[0:3] N[4:6]
// / \ / \
// N[0:1] N[2:3] N[4:5] N[6]
// / \ / \ / \
// N[0] N[1] N[2] N[3] N[4] N[5]
//
// submission codes start here

struct NumArray {
tree: Vec<i32>,
n: usize,
}

/**
* `&self` means the method takes an immutable reference.
* If you need a mutable reference, change it to `&mut self` instead.
*/
impl NumArray {
fn new(nums: Vec<i32>) -> Self {
let n = nums.len();
let mut tree = vec![0; 4*n];
if n > 0 {
NumArray::build(1, 0, n-1, &mut tree, &nums);
}
NumArray{tree: tree, n: n}
}

fn update(&mut self, i: i32, val: i32) {
NumArray::update_internal(i as usize, val, 1, 0, self.n-1, &mut self.tree);
}

fn sum_range(&self, i: i32, j: i32) -> i32 {
NumArray::sum(1, 0, self.n-1, i as usize, j as usize, &self.tree)
}

fn build(node: usize, start: usize, end: usize, tree: &mut Vec<i32>, nums: &Vec<i32>) {
if start == end {
tree[node] = nums[start];
} else {
let mid = (start + end) / 2;
NumArray::build(2*node, start, mid, tree, nums);
NumArray::build(2*node+1, mid+1, end, tree, nums);
tree[node] = tree[2*node] + tree[2*node+1];
}
}

fn update_internal(i: usize, val: i32, node: usize, start: usize, end: usize, tree: &mut Vec<i32>) {
if start == end {
tree[node] = val;
} else {
let mid = (start + end) / 2;
if i <= mid {
NumArray::update_internal(i, val, 2*node, start, mid, tree);
} else {
NumArray::update_internal(i, val, 2*node+1, mid+1, end, tree);
}
tree[node] = tree[2*node] + tree[2*node+1];
}
}

fn sum(node: usize, start: usize, end: usize, left: usize, right: usize, tree: &Vec<i32>) -> i32 {
if right < start || left > end {
// not in range
0
} else if left <= start && end <= right {
// completely in range
tree[node]
} else {
// partially in range
let mid = (start + end) / 2;
NumArray::sum(2*node, start, mid, left, right, tree) +
NumArray::sum(2*node+1, mid+1, end, left, right ,tree)
}
}
}

/**
* Your NumArray object will be instantiated and called as such:
* let obj = NumArray::new(nums);
* obj.update(i, val);
* let ret_2: i32 = obj.sum_range(i, j);
*/

// submission codes end

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_307() {
let _empty = NumArray::new(vec![]);
let mut tree = NumArray::new(vec![1,1,1,1,1,1,1,1,1,1]);
assert_eq!(tree.sum_range(0, 6), 7);
tree.update(0, 2);
assert_eq!(tree.sum_range(0, 6), 8);
tree.update(1, 2);
assert_eq!(tree.sum_range(0, 2), 5);
tree.update(6, 10);
assert_eq!(tree.sum_range(6, 6), 10);
}
}

0 comments on commit 0e10183

Please sign in to comment.