持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情
801. 使序列递增的最小交换次数
我们有两个长度相等且不为空的整型数组 nums1 和 nums2 。在一次操作中,我们可以交换 nums1[i] 和 nums2[i]的元素。
例如,如果 nums1 = [1,2,3,8] , nums2 =[5,6,7,4] ,你可以交换 i = 3 处的元素,得到 nums1 =[1,2,3,4] 和 nums2 =[5,6,7,8] 。
返回 使 nums1 和 nums2 严格递增 所需操作的最小次数 。
数组 arr 严格递增 且 arr[0] < arr[1] < arr[2] < ... < arr[arr.length - 1] 。
思路
要求最小的交换次数
首先,我们若是枚举所有操作,一共有多少种操作呢?
然后,我们可以先考虑使用dfs去枚举这个状态,就可以得到最少的答案了
但是,我们的复杂度太高了 是一个天文数字!
绝对不可能在一秒钟之内运算完(也许未来可以?
我们得考虑一下优化问题
优化,我们观察一下数组的前后两项之间的关系呢?
所以,我们就可以对于每一项,去枚举它上面一项所变化的策略,并以此来枚举本项交换的策略
每次枚举共4种情况
所以,整体时间复杂度即为
递推方程式为:
代码
use std::cmp::{max, min};
use std::mem::swap;
impl Solution {
pub fn min_swap(nums1: Vec<i32>, nums2: Vec<i32>) -> i32 {
let n = nums1.len();
const INF: i32 = 0x3f3f3f3f;
let mut dp: Vec<[i32; 2]> = vec![];
dp.resize(n, [INF, INF]);
dp[0][0] = 0;
dp[0][1] = 1;
for i in 1..n {
let (mut a, mut b, mut x, mut y) =
(nums1[i], nums2[i], nums1[i - 1], nums2[i - 1]);
for j in 0..2 as usize {
for k in 0..2 as usize {
if x < a && y < b {
dp[i][j] = min(dp[i][j], dp[i - 1][k] + j as i32);
}
swap(&mut x, &mut y);
}
swap(&mut a, &mut b);
}
}
return min(dp[n - 1][0], dp[n - 1][1]);
}
}