Reputation: 575
I'm trying to return sum of 3 largest numbers in an array like this:
fn max_tri_sum(arr: &[i32]) -> i32 {
arr.sort();
arr[0]+arr[1]+arr[2]
}
but I keep getting this error:
error[E0596]: cannot borrow `*arr` as mutable, as it is behind a `&` reference
fn max_tri_sum(arr: &[i32]) -> i32 {
------ help: consider changing this to be a mutable reference: `&mut [i32]`
arr.sort();
^^^ `arr` is a `&` reference, so the data it refers to cannot be borrowed as mutable
I shouldn't change arr: &[i32]
to arr: &mut [i32]
because of some restrictions. So what can I do about it?
P.S: I tried to clone arr
to a mutable variable but got other errors:
fn max_tri_sum(arr: &[i32]) -> i32 {
let a: &mut [i32] = *arr.clone();
a.sort();
a[0]+a[1]+a[2]
}
Upvotes: 2
Views: 1136
Reputation: 2533
In Rust, you can't have a variable that has both reference and mutable reference in the same scope.
You have several choices :
fn max_tri_sum(arr: &[i32]) -> i32 {
let mut maxes = [0, 0, 0];
for &el in arr {
if el > maxes[0] && el < maxes[1] {
maxes[0] = el;
} else if el > maxes[1] && el < maxes[2] {
if maxes[1] > maxes[0] {
maxes[0] = maxes[1];
}
maxes[1] = el;
} else if el > maxes[2] {
if maxes[2] > maxes[1] {
maxes[1] = maxes[2];
}
maxes[2] = el;
}
}
maxes[0] + maxes[1] + maxes[2]
}
Vec
from the slice, and then do all the operations on it (which requires allocation, but should be fine for small Vec
s). fn max_tri_sum(arr: &[i32]) -> i32 {
let mut arr = Vec::from(arr);
arr.sort();
arr[0] + arr[1] + arr[2]
}
I would also like to point that sort
sorts from smallest to biggest, so the index 0, 1, 2, ...
would be the smallest values in the array, which I don't think is what you want to do!
Upvotes: 1
Reputation: 215077
You could also use a BinaryHeap to store the three largest values so far and replace the smallest value while looping through the array:
use std::collections::BinaryHeap;
fn max_tri_sum(arr: &[i32]) -> i32 {
let mut heap = BinaryHeap::new();
heap.push(-arr[0]);
heap.push(-arr[1]);
heap.push(-arr[2]);
for e in arr[3..].iter() {
if -e < *heap.peek().unwrap() {
heap.pop();
heap.push(-e);
}
}
-heap.drain().sum::<i32>()
}
Or if you prefer the sort option, you can convert the slice to a vector:
fn max_tri_sum(arr: &[i32]) -> i32 {
let mut arr1 = arr.to_vec();
arr1.sort_by(|a, b| b.cmp(a));
arr1[0] + arr1[1] + arr1[2]
}
Upvotes: 2