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, } 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); } }