Skip to content

Commit 3b5b9ea

Browse files
committed
Add quick select solution to problem 3075: Maximize Happiness of Selected Children
1 parent bb4c62a commit 3b5b9ea

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

src/problem_3075_maximize_happiness_of_selected_children/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod greedy;
2+
pub mod quick_select;
23

34
pub trait Solution {
45
fn maximum_happiness_sum(happiness: Vec<i32>, k: i32) -> i64;
@@ -14,6 +15,7 @@ mod tests {
1415
((&[1, 1, 1, 1], 2), 1),
1516
((&[2, 3, 4, 5], 1), 5),
1617
((&[12, 1, 42], 3), 53),
18+
((&[442, 986, 309, 943], 4), 2674),
1719
];
1820

1921
for ((happiness, k), expected) in test_cases {
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
pub struct Solution;
2+
3+
// ------------------------------------------------------ snip ------------------------------------------------------ //
4+
5+
use std::cmp::Ordering;
6+
7+
impl Solution {
8+
fn partition(values: &mut [u32], key: u32) -> usize {
9+
// +------+-------+-----------+---------+
10+
// | Less | Equal | Unchecked | Greater |
11+
// +------+-------+-----------+---------+
12+
13+
let mut equal_start = 0;
14+
let mut unchecked_start = 0;
15+
let mut greater_start = values.len();
16+
17+
while unchecked_start < greater_start {
18+
match values[unchecked_start].cmp(&key) {
19+
Ordering::Less => {
20+
values.swap(equal_start, unchecked_start);
21+
22+
equal_start += 1;
23+
unchecked_start += 1;
24+
}
25+
Ordering::Equal => unchecked_start += 1,
26+
Ordering::Greater => {
27+
greater_start -= 1;
28+
29+
values.swap(unchecked_start, greater_start);
30+
}
31+
}
32+
}
33+
34+
(values.len() / 2).clamp(equal_start, unchecked_start - 1)
35+
}
36+
37+
pub fn maximum_happiness_sum(happiness: Vec<i32>, k: i32) -> i64 {
38+
let mut happiness = happiness.into_iter().map(i32::cast_unsigned).collect::<Vec<_>>();
39+
let n = happiness.len();
40+
let k = k.cast_unsigned() as usize;
41+
42+
happiness.select_nth_unstable(n - k);
43+
44+
let mut window = &mut happiness[n - k..];
45+
let mut right_length = 0;
46+
47+
while !window.is_empty() {
48+
let key = window[window.len() / 2];
49+
let middle = Self::partition(window, key);
50+
51+
let candidate_right_length = window.len() - middle + right_length;
52+
53+
window = if window[middle] < candidate_right_length as u32 {
54+
&mut window[middle + 1..]
55+
} else {
56+
right_length = candidate_right_length;
57+
58+
&mut window[..middle]
59+
};
60+
}
61+
62+
let selected = &happiness[n - right_length..];
63+
let selected_len = selected.len() as u64;
64+
65+
let sum = selected
66+
.iter()
67+
.fold(0_u64, |sum, &happiness| sum + u64::from(happiness));
68+
69+
let penalty = selected_len * (selected_len - 1) / 2;
70+
71+
(sum - penalty).cast_signed()
72+
}
73+
}
74+
75+
// ------------------------------------------------------ snip ------------------------------------------------------ //
76+
77+
impl super::Solution for Solution {
78+
fn maximum_happiness_sum(happiness: Vec<i32>, k: i32) -> i64 {
79+
Self::maximum_happiness_sum(happiness, k)
80+
}
81+
}
82+
83+
#[cfg(test)]
84+
mod tests {
85+
#[test]
86+
fn test_solution() {
87+
super::super::tests::run::<super::Solution>();
88+
}
89+
}

0 commit comments

Comments
 (0)