ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DeepSeek LeetCode 3892. 产生至少 K 个峰值的最少操作次数 Rust实现

DeepSeek    LeetCode 3892. 产生至少 K 个峰值的最少操作次数 Rust实现 我来提供一个更优化的 Rust 实现使用滚动数组和更清晰的逻辑rustimpl Solution {pub fn min_operations(nums: Veci32, k: i32) - i32 {let n nums.len();let k k as usize;// 特殊情况不需要峰值if k 0 {return 0;}// 环形数组最多 n/2 个峰值if k n / 2 {return -1;}const INF: i64 1_000_000_000_000_000_000;// 计算将位置 i 变为峰值的最小代价// 需要同时大于左右邻居let calc_cost |i: usize, nums: [i32]| - i64 {let left if i 0 { nums[n - 1] } else { nums[i - 1] };let right if i n - 1 { nums[0] } else { nums[i 1] };let target left.max(right) 1;(target - nums[i]).max(0) as i64};// 定义一个闭包来处理 DP// first_is_peak: 第一个位置索引0是否作为峰值let run_dp |first_is_peak: bool| - i64 {// dp[j][0/1]: 处理完当前元素形成 j 个峰值当前元素是否为峰值let mut dp vec![[INF, INF]; k 1];// 初始化第一个位置if first_is_peak {// 第一个位置作为峰值if k 1 {dp[1][1] calc_cost(0, nums);}// 第一个位置不作为峰值dp[0][0] 0;} else {// 第一个位置不作为峰值且不允许作为峰值dp[0][0] 0;}// 处理后续位置for i in 1..n {let mut new_dp vec![[INF, INF]; k 1];// 检查当前位置是否允许作为峰值// 如果是最后一个位置需要确保它与第一个位置不冲突let can_be_peak if i n - 1 {!first_is_peak // 如果第一个是峰值最后一个就不能是峰值} else {true};for j in 0..k {// 情况1当前位置不作为峰值// 前一个位置可以是峰值或非峰值let min_prev dp[j][0].min(dp[j][1]);new_dp[j][0] new_dp[j][0].min(min_prev);// 情况2当前位置作为峰值if can_be_peak j 0 dp[j - 1][0] INF {let cost calc_cost(i, nums);// 前一个位置必须是非峰值new_dp[j][1] new_dp[j][1].min(dp[j - 1][0] cost);}}dp new_dp;}// 返回形成至少 k 个峰值的最小代价// 最后一个位置可以是峰值或非峰值dp[k][0].min(dp[k][1])};// 情况1第一个位置不作为峰值let ans1 run_dp(false);// 情况2第一个位置作为峰值let ans2 run_dp(true);let ans ans1.min(ans2);if ans INF { -1 } else { ans as i32 }}}更简洁的版本使用单行数组rustimpl Solution {pub fn min_operations(nums: Veci32, k: i32) - i32 {let n nums.len();let k k as usize;if k 0 { return 0; }if k n / 2 { return -1; }const INF: i64 1_000_000_000_000_000_000;// 代价计算函数let cost |i: usize, nums: [i32]| - i64 {let l if i 0 { nums[n-1] } else { nums[i-1] };let r if i n-1 { nums[0] } else { nums[i1] };(l.max(r) 1 - nums[i]).max(0) as i64};// DP 运行函数let solve |first_peak: bool| - i64 {let mut dp vec![[INF, INF]; k 1];if first_peak {dp[1][1] cost(0, nums);dp[0][0] 0;} else {dp[0][0] 0;}for i in 1..n {let mut ndp vec![[INF, INF]; k 1];let can_peak i n - 1 || !first_peak;for j in 0..k {// 不作为峰值ndp[j][0] ndp[j][0].min(dp[j][0].min(dp[j][1]));// 作为峰值if can_peak j 0 {ndp[j][1] ndp[j][1].min(dp[j-1][0] cost(i, nums));}}dp ndp;}dp[k][0].min(dp[k][1])};let ans solve(false).min(solve(true));if ans INF { -1 } else { ans as i32 }}}复杂度分析· 时间复杂度O(n × k)其中 n 是数组长度。· 空间复杂度O(k)使用了滚动数组。关键点说明1. 环形处理通过分情况讨论 nums[0] 是否作为峰值避免环形带来的首尾冲突。2. 峰值条件一个位置是峰值必须严格大于左右邻居。3. DP 状态dp[j][p] 表示处理完当前元素后已有 j 个峰值当前元素是否为峰值p0/1的最小操作数。4. 边界处理最后一个位置是否能作为峰值取决于第一个位置是否已经是峰值。
返回列表