65 lines
1.2 KiB
Rust
65 lines
1.2 KiB
Rust
use std::cmp;
|
||
|
||
// We are guaranteed ‹n ∈ ⟨1 ; 10⁴⟩›
|
||
const UPPER_BOUND: i32 = 2000000000;
|
||
|
||
// Flag for unknown values
|
||
const UNKNOWN: i32 = -1;
|
||
|
||
struct Solver {
|
||
dp: Vec<i32>,
|
||
}
|
||
|
||
impl Solver {
|
||
fn new(n: i32) -> Self {
|
||
let mut dp = vec![UNKNOWN; (n as usize) + 1];
|
||
dp[0] = 0;
|
||
|
||
Self { dp }
|
||
}
|
||
|
||
fn solve(&mut self, n: i32) -> i32 {
|
||
if n < 0 {
|
||
return UPPER_BOUND;
|
||
}
|
||
|
||
let idx = n as usize;
|
||
if self.dp[idx] != UNKNOWN {
|
||
return self.dp[idx];
|
||
}
|
||
|
||
self.dp[idx] = UPPER_BOUND;
|
||
for i in (1..=n).take_while(|i| i * i <= n) {
|
||
self.dp[idx] = cmp::min(self.dp[idx], 1 + self.solve(n - i * i));
|
||
}
|
||
|
||
self.dp[idx]
|
||
}
|
||
}
|
||
|
||
struct Solution {}
|
||
impl Solution {
|
||
pub fn num_squares(n: i32) -> i32 {
|
||
Solver::new(n).solve(n)
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_1() {
|
||
assert_eq!(Solution::num_squares(12), 3);
|
||
}
|
||
|
||
#[test]
|
||
fn test_2() {
|
||
assert_eq!(Solution::num_squares(13), 2);
|
||
}
|
||
|
||
#[test]
|
||
fn test_3() {
|
||
assert_eq!(Solution::num_squares(55), 4);
|
||
}
|
||
}
|